diff options
-rw-r--r-- | src/Output.cxx | 8 | ||||
-rw-r--r-- | src/RunClang.cxx | 51 | ||||
-rw-r--r-- | test/CMakeLists.txt | 6 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-member-access-mutable-xml.txt | 24 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-member-access-xml.txt | 22 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-member-array-xml.txt | 20 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-member-const-xml.txt | 16 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-member-reference-xml.txt | 16 | ||||
-rw-r--r-- | test/expect/gccxml.Class-implicit-members-xml.txt | 20 | ||||
-rw-r--r-- | test/input/Class-implicit-member-access-mutable.cxx | 10 | ||||
-rw-r--r-- | test/input/Class-implicit-member-access.cxx | 9 | ||||
-rw-r--r-- | test/input/Class-implicit-member-array.cxx | 3 | ||||
-rw-r--r-- | test/input/Class-implicit-member-const.cxx | 5 | ||||
-rw-r--r-- | test/input/Class-implicit-member-reference.cxx | 5 | ||||
-rw-r--r-- | test/input/Class-implicit-members.cxx | 7 |
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; + } +}; |