summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Output.cxx8
-rw-r--r--src/RunClang.cxx51
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/expect/gccxml.Class-implicit-member-access-mutable-xml.txt24
-rw-r--r--test/expect/gccxml.Class-implicit-member-access-xml.txt22
-rw-r--r--test/expect/gccxml.Class-implicit-member-array-xml.txt20
-rw-r--r--test/expect/gccxml.Class-implicit-member-const-xml.txt16
-rw-r--r--test/expect/gccxml.Class-implicit-member-reference-xml.txt16
-rw-r--r--test/expect/gccxml.Class-implicit-members-xml.txt20
-rw-r--r--test/input/Class-implicit-member-access-mutable.cxx10
-rw-r--r--test/input/Class-implicit-member-access.cxx9
-rw-r--r--test/input/Class-implicit-member-array.cxx3
-rw-r--r--test/input/Class-implicit-member-const.cxx5
-rw-r--r--test/input/Class-implicit-member-reference.cxx5
-rw-r--r--test/input/Class-implicit-members.cxx7
15 files changed, 219 insertions, 3 deletions
diff --git a/src/Output.cxx b/src/Output.cxx
index dab1230..08519cc 100644
--- a/src/Output.cxx
+++ b/src/Output.cxx
@@ -26,7 +26,6 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Sema/Sema.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
@@ -405,6 +404,11 @@ unsigned int ASTVisitor::AddDumpNode(clang::Decl const* d, bool complete) {
break;
}
+ // Skip invalid declarations.
+ if(d->isInvalidDecl()) {
+ return 0;
+ }
+
return this->AddDumpNodeImpl(d, complete);
}
@@ -1150,8 +1154,6 @@ void ASTVisitor::OutputRecordDecl(clang::RecordDecl const* d,
void ASTVisitor::OutputCXXRecordDecl(clang::CXXRecordDecl const* d,
DumpNode const* dn)
{
- this->CI.getSema().ForceDeclarationOfImplicitMembers(
- const_cast<clang::CXXRecordDecl*>(d));
this->OutputRecordDecl(d, dn);
}
diff --git a/src/RunClang.cxx b/src/RunClang.cxx
index e9f561d..55f8024 100644
--- a/src/RunClang.cxx
+++ b/src/RunClang.cxx
@@ -22,6 +22,8 @@
#include <cxsys/SystemTools.hxx>
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -33,6 +35,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Sema.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
@@ -51,6 +54,54 @@ public:
std::vector<std::string> const& startNames):
CI(ci), OS(os), StartNames(startNames) {}
+ void AddImplicitMembers(clang::CXXRecordDecl* rd) {
+ clang::Sema& sema = this->CI.getSema();
+ sema.ForceDeclarationOfImplicitMembers(rd);
+
+# define DEFINE_IMPLICIT(name, decl) do { \
+ clang::Sema::SFINAETrap trap(sema, /*AccessChecking=*/ true); \
+ sema.DefineImplicit##name(clang::SourceLocation(), (decl)); \
+ if (trap.hasErrorOccurred()) { \
+ (decl)->setInvalidDecl(); \
+ } \
+ } while(0)
+
+ for(clang::DeclContext::decl_iterator i = rd->decls_begin(),
+ e = rd->decls_end(); i != e; ++i) {
+ clang::CXXMethodDecl* m = clang::dyn_cast<clang::CXXMethodDecl>(*i);
+ if(m && m->isImplicit() && !m->isDeleted() &&
+ !m->doesThisDeclarationHaveABody()) {
+ if (clang::CXXConstructorDecl* c =
+ clang::dyn_cast<clang::CXXConstructorDecl>(m)) {
+ if (c->isDefaultConstructor()) {
+ DEFINE_IMPLICIT(DefaultConstructor, c);
+ } else if (c->isCopyConstructor()) {
+ DEFINE_IMPLICIT(CopyConstructor, c);
+ } else if (c->isMoveConstructor()) {
+ DEFINE_IMPLICIT(MoveConstructor, c);
+ }
+ } else if (clang::CXXDestructorDecl* d =
+ clang::dyn_cast<clang::CXXDestructorDecl>(m)) {
+ DEFINE_IMPLICIT(Destructor, d);
+ } else if (m->isCopyAssignmentOperator()) {
+ DEFINE_IMPLICIT(CopyAssignment, m);
+ } else if (m->isMoveAssignmentOperator()) {
+ DEFINE_IMPLICIT(MoveAssignment, m);
+ }
+ }
+ }
+
+# undef DEFINE_IMPLICIT
+ }
+
+ void HandleTagDeclDefinition(clang::TagDecl* d) {
+ if(clang::CXXRecordDecl* rd = clang::dyn_cast<clang::CXXRecordDecl>(d)) {
+ if(!rd->isDependentContext()) {
+ this->AddImplicitMembers(rd);
+ }
+ }
+ }
+
void HandleTranslationUnit(clang::ASTContext& ctx) {
outputXML(this->CI, ctx, this->OS, this->StartNames);
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0441ce7..4749b58 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -86,6 +86,12 @@ castxml_test_gccxml(Class-base-typedef)
castxml_test_gccxml(Class-bases)
castxml_test_gccxml(Class-forward)
castxml_test_gccxml(Class-friends)
+castxml_test_gccxml(Class-implicit-member-access)
+castxml_test_gccxml(Class-implicit-member-access-mutable)
+castxml_test_gccxml(Class-implicit-member-array)
+castxml_test_gccxml(Class-implicit-member-const)
+castxml_test_gccxml(Class-implicit-member-reference)
+castxml_test_gccxml(Class-implicit-members)
castxml_test_gccxml(Class-incomplete)
castxml_test_gccxml(Class-incomplete-twice)
castxml_test_gccxml(Class-member-template)
diff --git a/test/expect/gccxml.Class-implicit-member-access-mutable-xml.txt b/test/expect/gccxml.Class-implicit-member-access-mutable-xml.txt
new file mode 100644
index 0000000..8e610e8
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-member-access-mutable-xml.txt
@@ -0,0 +1,24 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:10" file="f1" line="10" members="_3 _4" bases="_5">
+ <Base type="_5" access="public" virtual="0"/>
+ </Class>
+ <Destructor id="_3" name="start" context="_1" access="public" location="f1:10" file="f1" line="10" inline="1" artificial="1"/>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:10" file="f1" line="10" inline="1" artificial="1"/>
+ <Class id="_5" name="base" context="_2" location="f1:1" file="f1" line="1" members="_6 _7 _8 _9 _10"/>
+ <Constructor id="_6" name="base" context="_5" access="protected" location="f1:3" file="f1" line="3"/>
+ <Destructor id="_7" name="base" context="_5" access="protected" location="f1:4" file="f1" line="4"/>
+ <Constructor id="_8" name="base" context="_5" access="private" location="f1:6" file="f1" line="6">
+ <Argument type="_11" location="f1:6" file="f1" line="6"/>
+ </Constructor>
+ <OperatorMethod id="_9" name="=" returns="_12" context="_5" access="private" location="f1:7" file="f1" line="7">
+ <Argument type="_11" location="f1:7" file="f1" line="7"/>
+ </OperatorMethod>
+ <Field id="_10" name="data" type="_13" context="_5" access="private" location="f1:8" file="f1" line="8" mutable="1"/>
+ <ReferenceType id="_11" type="_5c"/>
+ <ReferenceType id="_12" type="_5"/>
+ <FundamentalType id="_13" name="int"/>
+ <Namespace id="_2" name="::"/>
+ <CvQualifiedType id="_5c" type="_5" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-member-access-mutable.cxx"/>
+</GCC_XML>$
diff --git a/test/expect/gccxml.Class-implicit-member-access-xml.txt b/test/expect/gccxml.Class-implicit-member-access-xml.txt
new file mode 100644
index 0000000..d3681b0
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-member-access-xml.txt
@@ -0,0 +1,22 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:9" file="f1" line="9" members="_3 _4" bases="_5">
+ <Base type="_5" access="public" virtual="0"/>
+ </Class>
+ <Destructor id="_3" name="start" context="_1" access="public" location="f1:9" file="f1" line="9" inline="1" artificial="1"/>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:9" file="f1" line="9" inline="1" artificial="1"/>
+ <Class id="_5" name="base" context="_2" location="f1:1" file="f1" line="1" members="_6 _7 _8 _9"/>
+ <Constructor id="_6" name="base" context="_5" access="protected" location="f1:3" file="f1" line="3"/>
+ <Destructor id="_7" name="base" context="_5" access="protected" location="f1:4" file="f1" line="4"/>
+ <Constructor id="_8" name="base" context="_5" access="private" location="f1:6" file="f1" line="6">
+ <Argument type="_10" location="f1:6" file="f1" line="6"/>
+ </Constructor>
+ <OperatorMethod id="_9" name="=" returns="_11" context="_5" access="private" location="f1:7" file="f1" line="7">
+ <Argument type="_10" location="f1:7" file="f1" line="7"/>
+ </OperatorMethod>
+ <ReferenceType id="_10" type="_5c"/>
+ <ReferenceType id="_11" type="_5"/>
+ <Namespace id="_2" name="::"/>
+ <CvQualifiedType id="_5c" type="_5" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-member-access.cxx"/>
+</GCC_XML>$
diff --git a/test/expect/gccxml.Class-implicit-member-array-xml.txt b/test/expect/gccxml.Class-implicit-member-array-xml.txt
new file mode 100644
index 0000000..f6eac01
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-member-array-xml.txt
@@ -0,0 +1,20 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:1" file="f1" line="1" members="_3 _4 _5 _6 _7"/>
+ <Field id="_3" name="data" type="_8" context="_1" access="private" location="f1:2" file="f1" line="2"/>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <Constructor id="_5" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1">
+ <Argument type="_9" location="f1:1" file="f1" line="1"/>
+ </Constructor>
+ <OperatorMethod id="_6" name="=" returns="_10" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1">
+ <Argument type="_9" location="f1:1" file="f1" line="1"/>
+ </OperatorMethod>
+ <Destructor id="_7" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <ArrayType id="_8" min="0" max="1" type="_11"/>
+ <ReferenceType id="_9" type="_1c"/>
+ <ReferenceType id="_10" type="_1"/>
+ <FundamentalType id="_11" name="int"/>
+ <Namespace id="_2" name="::"/>
+ <CvQualifiedType id="_1c" type="_1" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-member-array.cxx"/>
+</GCC_XML>$
diff --git a/test/expect/gccxml.Class-implicit-member-const-xml.txt b/test/expect/gccxml.Class-implicit-member-const-xml.txt
new file mode 100644
index 0000000..8accf1a
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-member-const-xml.txt
@@ -0,0 +1,16 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:1" file="f1" line="1" members="_3 _4 _5 _6"/>
+ <Field id="_3" name="data" type="_8c" context="_1" access="private" location="f1:2" file="f1" line="2"/>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:4" file="f1" line="4"/>
+ <Constructor id="_5" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1">
+ <Argument type="_9" location="f1:1" file="f1" line="1"/>
+ </Constructor>
+ <Destructor id="_6" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <CvQualifiedType id="_8c" type="_8" const="1"/>
+ <FundamentalType id="_8" name="int"/>
+ <ReferenceType id="_9" type="_1c"/>
+ <Namespace id="_2" name="::"/>
+ <CvQualifiedType id="_1c" type="_1" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-member-const.cxx"/>
+</GCC_XML>$
diff --git a/test/expect/gccxml.Class-implicit-member-reference-xml.txt b/test/expect/gccxml.Class-implicit-member-reference-xml.txt
new file mode 100644
index 0000000..72b0862
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-member-reference-xml.txt
@@ -0,0 +1,16 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:1" file="f1" line="1" members="_3 _4 _5 _6"/>
+ <Field id="_3" name="ref" type="_7" context="_1" access="private" location="f1:2" file="f1" line="2"/>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:4" file="f1" line="4"/>
+ <Constructor id="_5" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1">
+ <Argument type="_8" location="f1:1" file="f1" line="1"/>
+ </Constructor>
+ <Destructor id="_6" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <ReferenceType id="_7" type="_9"/>
+ <ReferenceType id="_8" type="_1c"/>
+ <Namespace id="_2" name="::"/>
+ <FundamentalType id="_9" name="int"/>
+ <CvQualifiedType id="_1c" type="_1" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-member-reference.cxx"/>
+</GCC_XML>$
diff --git a/test/expect/gccxml.Class-implicit-members-xml.txt b/test/expect/gccxml.Class-implicit-members-xml.txt
new file mode 100644
index 0000000..58aed61
--- /dev/null
+++ b/test/expect/gccxml.Class-implicit-members-xml.txt
@@ -0,0 +1,20 @@
+^<\?xml version="1.0"\?>
+<GCC_XML[^>]*>
+ <Class id="_1" name="start" context="_2" location="f1:1" file="f1" line="1" members="_3 _4 _5 _6 _7"/>
+ <Method id="_3" name="method" returns="_1" context="_1" access="private" location="f1:2" file="f1" line="2" inline="1">
+ <Argument name="x" type="_8" location="f1:2" file="f1" line="2"/>
+ </Method>
+ <Constructor id="_4" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <Constructor id="_5" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1" throws="">
+ <Argument type="_8" location="f1:1" file="f1" line="1"/>
+ </Constructor>
+ <OperatorMethod id="_6" name="=" returns="_9" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1" throws="">
+ <Argument type="_8" location="f1:1" file="f1" line="1"/>
+ </OperatorMethod>
+ <Destructor id="_7" name="start" context="_1" access="public" location="f1:1" file="f1" line="1" inline="1" artificial="1"/>
+ <ReferenceType id="_8" type="_1c"/>
+ <ReferenceType id="_9" type="_1"/>
+ <Namespace id="_2" name="::"/>
+ <CvQualifiedType id="_1c" type="_1" const="1"/>
+ <File id="f1" name=".*/test/input/Class-implicit-members.cxx"/>
+</GCC_XML>$
diff --git a/test/input/Class-implicit-member-access-mutable.cxx b/test/input/Class-implicit-member-access-mutable.cxx
new file mode 100644
index 0000000..8d9aaec
--- /dev/null
+++ b/test/input/Class-implicit-member-access-mutable.cxx
@@ -0,0 +1,10 @@
+class base {
+protected:
+ base();
+ ~base();
+private:
+ base(base const&);
+ base& operator=(base const&);
+ mutable int data;
+};
+class start: public base {};
diff --git a/test/input/Class-implicit-member-access.cxx b/test/input/Class-implicit-member-access.cxx
new file mode 100644
index 0000000..d9992bc
--- /dev/null
+++ b/test/input/Class-implicit-member-access.cxx
@@ -0,0 +1,9 @@
+class base {
+protected:
+ base();
+ ~base();
+private:
+ base(base const&);
+ base& operator=(base const&);
+};
+class start: public base {};
diff --git a/test/input/Class-implicit-member-array.cxx b/test/input/Class-implicit-member-array.cxx
new file mode 100644
index 0000000..44002dc
--- /dev/null
+++ b/test/input/Class-implicit-member-array.cxx
@@ -0,0 +1,3 @@
+class start {
+ int data[2];
+};
diff --git a/test/input/Class-implicit-member-const.cxx b/test/input/Class-implicit-member-const.cxx
new file mode 100644
index 0000000..59221af
--- /dev/null
+++ b/test/input/Class-implicit-member-const.cxx
@@ -0,0 +1,5 @@
+class start {
+ int const data;
+public:
+ start();
+};
diff --git a/test/input/Class-implicit-member-reference.cxx b/test/input/Class-implicit-member-reference.cxx
new file mode 100644
index 0000000..67da21d
--- /dev/null
+++ b/test/input/Class-implicit-member-reference.cxx
@@ -0,0 +1,5 @@
+class start {
+ int& ref;
+public:
+ start();
+};
diff --git a/test/input/Class-implicit-members.cxx b/test/input/Class-implicit-members.cxx
new file mode 100644
index 0000000..2d79ee5
--- /dev/null
+++ b/test/input/Class-implicit-members.cxx
@@ -0,0 +1,7 @@
+class start {
+ start method(start const& x) {
+ start s;
+ s = x;
+ return s;
+ }
+};