Author: rtrieu Date: Fri Feb 17 01:19:24 2017 New Revision: 295427 URL: http://llvm.org/viewvc/llvm-project?rev=295427&view=rev Log: Revert r295421, new ODR checker for modules, to fix build bot.
Removed: cfe/trunk/include/clang/AST/ODRHash.h cfe/trunk/lib/AST/ODRHash.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/AST/Stmt.h cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td cfe/trunk/lib/AST/CMakeLists.txt cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/lib/AST/StmtProfile.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/Modules/merge-using-decls.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Feb 17 01:19:24 2017 @@ -458,9 +458,6 @@ class CXXRecordDecl : public RecordDecl /// \brief Whether we are currently parsing base specifiers. unsigned IsParsingBaseSpecifiers : 1; - /// \brief A hash of parts of the class to help in ODR checking. - unsigned ODRHash; - /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -706,9 +703,6 @@ public: return data().IsParsingBaseSpecifiers; } - void computeODRHash(); - unsigned getODRHash() const { return data().ODRHash; } - /// \brief Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); Removed: cfe/trunk/include/clang/AST/ODRHash.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ODRHash.h?rev=295426&view=auto ============================================================================== --- cfe/trunk/include/clang/AST/ODRHash.h (original) +++ cfe/trunk/include/clang/AST/ODRHash.h (removed) @@ -1,82 +0,0 @@ -//===-- ODRHash.h - Hashing to diagnose ODR failures ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the declaration of the ODRHash class, which calculates -/// a hash based on AST nodes, which is stable across different runs. -/// -//===----------------------------------------------------------------------===// - -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TemplateBase.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" - -namespace clang { - -class Decl; -class IdentifierInfo; -class NestedNameSpecifer; -class Stmt; -class TemplateParameterList; - -// ODRHash is used to calculate a hash based on AST node contents that -// does not rely on pointer addresses. This allows the hash to not vary -// between runs and is usable to detect ODR problems in modules. To use, -// construct an ODRHash object, then call Add* methods over the nodes that -// need to be hashed. Then call CalculateHash to get the hash value. -// Typically, only one Add* call is needed. clear can be called to reuse the -// object. -class ODRHash { - // Use DenseMaps to convert between Decl and Type pointers and an index value. - llvm::DenseMap<const Decl*, unsigned> DeclMap; - llvm::DenseMap<const Type*, unsigned> TypeMap; - - // Save space by processing bools at the end. - llvm::SmallVector<bool, 128> Bools; - - llvm::FoldingSetNodeID ID; - -public: - ODRHash() {} - - // Use this for ODR checking classes between modules. This method compares - // more information than the AddDecl class. - void AddCXXRecordDecl(const CXXRecordDecl *Record); - - // Process SubDecls of the main Decl. This method calls the DeclVisitor - // while AddDecl does not. - void AddSubDecl(const Decl *D); - - // Reset the object for reuse. - void clear(); - - // Add booleans to ID and uses it to calculate the hash. - unsigned CalculateHash(); - - // Add AST nodes that need to be processed. - void AddDecl(const Decl *D); - void AddType(const Type *T); - void AddQualType(QualType T); - void AddStmt(const Stmt *S); - void AddIdentifierInfo(const IdentifierInfo *II); - void AddNestedNameSpecifier(const NestedNameSpecifier *NNS); - void AddTemplateName(TemplateName Name); - void AddDeclarationName(DeclarationName Name); - void AddTemplateArgument(TemplateArgument TA); - void AddTemplateParameterList(const TemplateParameterList *TPL); - - // Save booleans until the end to lower the size of data to process. - void AddBoolean(bool value); -}; - -} // end namespace clang Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Fri Feb 17 01:19:24 2017 @@ -39,7 +39,6 @@ namespace clang { class Expr; class IdentifierInfo; class LabelDecl; - class ODRHash; class ParmVarDecl; class PrinterHelper; struct PrintingPolicy; @@ -437,8 +436,6 @@ public: /// written in the source. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const; - - void ProcessODRHash(llvm::FoldingSetNodeID &ID, ODRHash& Hash) const; }; /// DeclStmt - Adaptor class for mixing declarations with statements and Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Fri Feb 17 01:19:24 2017 @@ -117,70 +117,6 @@ def note_module_odr_violation_different_ def err_module_odr_violation_different_instantiations : Error< "instantiation of %q0 is different in different modules">; -def err_module_odr_violation_mismatch_decl : Error< - "%q0 has different definitions in different modules; first difference is " - "%select{definition in module '%2'|defined here}1 found " - "%select{end of class|public access specifier|private access specifier|" - "protected access specifier|friend declaration|enum|" - "static assert|typedef|type alias|method|constructor|destructor|" - "conversion operator|field|other}3">; -def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " - "%select{end of class|public access specifier|private access specifier|" - "protected access specifier|friend declaration|enum|" - "static assert|typedef|type alias|method|constructor|destructor|" - "conversion operator|field|other}1">; - -def err_module_odr_violation_mismatch_decl_diff : Error< - "%q0 has different definitions in different modules; first difference is " - "%select{definition in module '%2'|defined here}1 found " - "%select{friend %4|enum %4|element %4 in enum %5|" - "element %4 in enum %5 with initializer|" - "element %4 in enum %5 with no initializer|" - "element %4 in enum %5 with initializer|" - "enum %4 has %5 element%s5|" - "static assert with condition|" - "static assert with message|" - "static assert with %select{|no}4 message|" - "%select{typedef|type alias}4 name %5|" - "method named %4|" - "method %4 is %select{non-|}5static|" - "method %4 is %select{not |}5inline|" - "method %4 is %select{not |}5const|" - "method %4 has %5 parameter%s5|" - "method %4 has %ordinal5 parameter %select{named %7|with no name}6|" - "method %4 has %ordinal5 parameter with type %6|" - "method %4 has %ordinal5 parameter with default argument|" - "method %4 has %ordinal5 parameter with %select{no |}6 default argument|" - "method %4 has %select{|no }5body|" - "method %4 has different body|" - "field %4|" - "%select{field|bitfield}5 %4|" - "%select{non-mutable|mutable}5 %4}3">; -def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " - "%select{other friend %2|other enum %2|different element %2 in enum %3|" - "element %2 in enum %3 with initializer|" - "element %2 in enum %3 with no initializer|" - "element %2 in enum %3 with different initializer|" - "enum %2 has %3 element%s3|" - "static assert with different condition|" - "static assert with different message|" - "static assert with %select{|no}2 message|" - "different %select{typedef|type alias}2 name %3|" - "method named %2|" - "method %2 is %select{non-|}3static|" - "method %2 is %select{not |}3inline|" - "method %2 is %select{not |}3const|" - "method %2 has %3 parameter%s3|" - "method %2 has %ordinal3 parameter %select{named %5|with no name}4|" - "method %2 has %ordinal3 parameter with type %4|" - "method %2 has %ordinal3 parameter with different default argument|" - "method %2 has %ordinal3 parameter with %select{no |}4default argument|" - "method %2 has %select{|no }3body|" - "method %2 has different body|" - "field %2|" - "%select{field|bitfield}3 %2|" - "%select{non-mutable|mutable}3 %2}1">; - def warn_module_uses_date_time : Warning< "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, InGroup<DiagGroup<"pch-date-time">>; Modified: cfe/trunk/lib/AST/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/AST/CMakeLists.txt (original) +++ cfe/trunk/lib/AST/CMakeLists.txt Fri Feb 17 01:19:24 2017 @@ -40,7 +40,6 @@ add_clang_library(clangAST MicrosoftMangle.cpp NestedNameSpecifier.cpp NSAPI.cpp - ODRHash.cpp OpenMPClause.cpp ParentMap.cpp RawCommentList.cpp Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Feb 17 01:19:24 2017 @@ -18,7 +18,6 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ODRHash.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" @@ -72,8 +71,8 @@ CXXRecordDecl::DefinitionData::Definitio ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), - IsParsingBaseSpecifiers(false), ODRHash(0), NumBases(0), NumVBases(0), - Bases(), VBases(), Definition(D), FirstFriend() {} + IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(), + VBases(), Definition(D), FirstFriend() {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -372,16 +371,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier data().IsParsingBaseSpecifiers = false; } -void CXXRecordDecl::computeODRHash() { - if (!DefinitionData) - return; - - ODRHash Hash; - Hash.AddCXXRecordDecl(this); - - DefinitionData->ODRHash = Hash.CalculateHash(); -} - void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // C++11 [class.copy]p11: // A defaulted copy/move constructor for a class X is defined as Removed: cfe/trunk/lib/AST/ODRHash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=295426&view=auto ============================================================================== --- cfe/trunk/lib/AST/ODRHash.cpp (original) +++ cfe/trunk/lib/AST/ODRHash.cpp (removed) @@ -1,935 +0,0 @@ -//===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file implements the ODRHash class, which calculates a hash based -/// on AST nodes, which is stable across different runs. -/// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ODRHash.h" - -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/TypeVisitor.h" - -using namespace clang; - - -// Hashing for Stmt is with Stmt::Profile, since they derive from the same base -// class. -void ODRHash::AddStmt(const Stmt *S) { - assert(S && "Expecting non-null pointer."); - S->ProcessODRHash(ID, *this); -} - -void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) { - assert(II && "Expecting non-null pointer."); - ID.AddString(II->getName()); -} - -void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - assert(NNS && "Expecting non-null pointer."); - const auto *Prefix = NNS->getPrefix(); - AddBoolean(Prefix); - if (Prefix) - AddNestedNameSpecifier(Prefix); - - auto Kind = NNS->getKind(); - ID.AddInteger(Kind); - switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierInfo(NNS->getAsIdentifier()); - break; - case NestedNameSpecifier::Namespace: - AddDecl(NNS->getAsNamespace()); - break; - case NestedNameSpecifier::NamespaceAlias: - AddDecl(NNS->getAsNamespaceAlias()); - break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - AddType(NNS->getAsType()); - break; - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - break; - } -} - -void ODRHash::AddTemplateName(TemplateName Name) { - const auto Kind = Name.getKind(); - ID.AddInteger(Kind); - AddBoolean(Name.isDependent()); - AddBoolean(Name.isInstantiationDependent()); - switch (Kind) { - case TemplateName::Template: - AddDecl(Name.getAsTemplateDecl()); - break; - case TemplateName::OverloadedTemplate: { - const auto *Storage = Name.getAsOverloadedTemplate(); - ID.AddInteger(Storage->size()); - for (const auto *ND : *Storage) { - AddDecl(ND); - } - break; - } - case TemplateName::QualifiedTemplate: { - const auto *QTN = Name.getAsQualifiedTemplateName(); - AddNestedNameSpecifier(QTN->getQualifier()); - AddBoolean(QTN->hasTemplateKeyword()); - AddDecl(QTN->getDecl()); - break; - } - case TemplateName::DependentTemplate: { - const auto *DTN = Name.getAsDependentTemplateName(); - AddBoolean(DTN->isIdentifier()); - if (DTN->isIdentifier()) { - AddIdentifierInfo(DTN->getIdentifier()); - } else { - ID.AddInteger(DTN->getOperator()); - } - break; - } - case TemplateName::SubstTemplateTemplateParm: { - const auto *Storage = Name.getAsSubstTemplateTemplateParm(); - AddDecl(Storage->getParameter()); - AddTemplateName(Storage->getReplacement()); - break; - } - case TemplateName::SubstTemplateTemplateParmPack: { - const auto *Storage = Name.getAsSubstTemplateTemplateParmPack(); - AddDecl(Storage->getParameterPack()); - AddTemplateArgument(Storage->getArgumentPack()); - break; - } - } -} - -void ODRHash::AddDeclarationName(DeclarationName Name) { - AddBoolean(Name.isEmpty()); - if (Name.isEmpty()) - return; - - auto Kind = Name.getNameKind(); - ID.AddInteger(Kind); - switch (Kind) { - case DeclarationName::Identifier: - AddIdentifierInfo(Name.getAsIdentifierInfo()); - break; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: { - Selector S = Name.getObjCSelector(); - AddBoolean(S.isNull()); - AddBoolean(S.isKeywordSelector()); - AddBoolean(S.isUnarySelector()); - unsigned NumArgs = S.getNumArgs(); - for (unsigned i = 0; i < NumArgs; ++i) { - AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); - } - break; - } - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - AddQualType(Name.getCXXNameType()); - break; - case DeclarationName::CXXOperatorName: - ID.AddInteger(Name.getCXXOverloadedOperator()); - break; - case DeclarationName::CXXLiteralOperatorName: - AddIdentifierInfo(Name.getCXXLiteralIdentifier()); - break; - case DeclarationName::CXXConversionFunctionName: - AddQualType(Name.getCXXNameType()); - break; - case DeclarationName::CXXUsingDirective: - break; - case DeclarationName::CXXDeductionGuideName: { - auto *Template = Name.getCXXDeductionGuideTemplate(); - AddBoolean(Template); - if (Template) { - AddDecl(Template); - } - } - } -} - -void ODRHash::AddTemplateArgument(TemplateArgument TA) { - const auto Kind = TA.getKind(); - ID.AddInteger(Kind); - switch (Kind) { - case TemplateArgument::Null: - llvm_unreachable("Require valid TemplateArgument"); - case TemplateArgument::Type: - AddQualType(TA.getAsType()); - break; - case TemplateArgument::Declaration: - AddDecl(TA.getAsDecl()); - break; - case TemplateArgument::NullPtr: - AddQualType(TA.getNullPtrType()); - break; - case TemplateArgument::Integral: - TA.getAsIntegral().Profile(ID); - AddQualType(TA.getIntegralType()); - break; - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - AddTemplateName(TA.getAsTemplateOrTemplatePattern()); - break; - case TemplateArgument::Expression: - AddStmt(TA.getAsExpr()); - break; - case TemplateArgument::Pack: - ID.AddInteger(TA.pack_size()); - for (auto SubTA : TA.pack_elements()) - AddTemplateArgument(SubTA); - break; - } -} - -void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) { - assert(TPL && "Expecting non-null pointer."); - ID.AddInteger(TPL->size()); - for (auto *ND : TPL->asArray()) { - AddSubDecl(ND); - } -} - -void ODRHash::clear() { - DeclMap.clear(); - TypeMap.clear(); - Bools.clear(); - ID.clear(); -} - -unsigned ODRHash::CalculateHash() { - // Append the bools to the end of the data segment backwards. This allows - // for the bools data to be compressed 32 times smaller compared to using - // ID.AddBoolean - const unsigned unsigned_bits = sizeof(unsigned) * CHAR_BIT; - const unsigned size = Bools.size(); - const unsigned remainder = size % unsigned_bits; - const unsigned loops = size / unsigned_bits; - auto I = Bools.rbegin(); - unsigned value = 0; - for (unsigned i = 0; i < remainder; ++i) { - value <<= 1; - value |= *I; - ++I; - } - ID.AddInteger(value); - - for (unsigned i = 0; i < loops; ++i) { - value = 0; - for (unsigned j = 0; j < unsigned_bits; ++j) { - value <<= 1; - value |= *I; - ++I; - } - ID.AddInteger(value); - } - - assert(I == Bools.rend()); - Bools.clear(); - return ID.ComputeHash(); -} - -// Process a Decl pointer. Add* methods call back into ODRHash while Visit* -// methods process the relevant parts of the Decl. -class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> { - typedef ConstDeclVisitor<ODRDeclVisitor> Inherited; - llvm::FoldingSetNodeID &ID; - ODRHash &Hash; - -public: - ODRDeclVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash) - : ID(ID), Hash(Hash) {} - - void AddDecl(const Decl *D) { - Hash.AddBoolean(D); - if (D) { - Hash.AddDecl(D); - } - } - - void AddStmt(const Stmt *S) { - Hash.AddBoolean(S); - if (S) { - Hash.AddStmt(S); - } - } - - void AddQualType(QualType T) { - Hash.AddQualType(T); - } - - void AddIdentifierInfo(const IdentifierInfo *II) { - Hash.AddBoolean(II); - if (II) { - Hash.AddIdentifierInfo(II); - } - } - - void AddTemplateParameterList(TemplateParameterList *TPL) { - Hash.AddBoolean(TPL); - if (TPL) { - Hash.AddTemplateParameterList(TPL); - } - } - - void AddTemplateArgument(TemplateArgument TA) { - Hash.AddTemplateArgument(TA); - } - - void Visit(const Decl *D) { - if (!D) - return; - if (D->isImplicit()) - return; - if (D->isInvalidDecl()) - return; - ID.AddInteger(D->getKind()); - - Inherited::Visit(D); - } - - void VisitDecl(const Decl *D) { - Inherited::VisitDecl(D); - } - - void VisitLabelDecl(const LabelDecl *D) { - Inherited::VisitLabelDecl(D); - } - - void VisitEnumDecl(const EnumDecl *D) { - const bool isFixed = D->isFixed(); - Hash.AddBoolean(isFixed); - if (isFixed) - AddQualType(D->getIntegerType()); - Hash.AddBoolean(D->isScoped()); - Hash.AddBoolean(D->isScopedUsingClassTag()); - - // TODO: Enums should have their own ODR hash. - for (auto *SubDecl : D->decls()) { - Hash.AddSubDecl(SubDecl); - } - - Inherited::VisitEnumDecl(D); - } - - void VisitEnumConstantDecl(const EnumConstantDecl *D) { - auto *E = D->getInitExpr(); - AddStmt(E); - - Inherited::VisitEnumConstantDecl(D); - } - - void VisitNamedDecl(const NamedDecl *D) { - AddIdentifierInfo(D->getIdentifier()); - Inherited::VisitNamedDecl(D); - } - - void VisitValueDecl(const ValueDecl *D) { - AddQualType(D->getType()); - Inherited::VisitValueDecl(D); - } - - void VisitParmVarDecl(const ParmVarDecl *D) { - AddStmt(D->getDefaultArg()); - Inherited::VisitParmVarDecl(D); - } - - void VisitAccessSpecDecl(const AccessSpecDecl *D) { - ID.AddInteger(D->getAccess()); - Inherited::VisitAccessSpecDecl(D); - } - - void VisitFriendDecl(const FriendDecl *D) { - TypeSourceInfo *TSI = D->getFriendType(); - Hash.AddBoolean(TSI); - if (TSI) - AddQualType(TSI->getType()); - else - AddDecl(D->getFriendDecl()); - - unsigned NumLists = D->getFriendTypeNumTemplateParameterLists(); - ID.AddInteger(NumLists); - for (unsigned i = 0; i < NumLists; ++i) - AddTemplateParameterList(D->getFriendTypeTemplateParameterList(i)); - Inherited::VisitFriendDecl(D); - } - - void VisitStaticAssertDecl(const StaticAssertDecl *D) { - AddStmt(D->getAssertExpr()); - AddStmt(D->getMessage()); - - Inherited::VisitStaticAssertDecl(D); - } - - void VisitTypedefNameDecl(const TypedefNameDecl *D) { - AddQualType(D->getUnderlyingType()); - - Inherited::VisitTypedefNameDecl(D); - } - - void VisitFunctionDecl(const FunctionDecl *D) { - // TODO: Functions should have their own ODR hashes. - AddStmt(D->hasBody() ? D->getBody() : nullptr); - - ID.AddInteger(D->getStorageClass()); - Hash.AddBoolean(D->isInlineSpecified()); - Hash.AddBoolean(D->isVirtualAsWritten()); - Hash.AddBoolean(D->isPure()); - Hash.AddBoolean(D->isDeletedAsWritten()); - ID.AddInteger(D->getOverloadedOperator()); - Inherited::VisitFunctionDecl(D); - } - - void VisitCXXMethodDecl(const CXXMethodDecl *D) { - Hash.AddBoolean(D->isStatic()); - Hash.AddBoolean(D->isInstance()); - Hash.AddBoolean(D->isConst()); - Hash.AddBoolean(D->isVolatile()); - Inherited::VisitCXXMethodDecl(D); - } - - void VisitCXXConstructorDecl(const CXXConstructorDecl *D) { - Hash.AddBoolean(D->isExplicitSpecified()); - unsigned NumCtorInits = 0; - llvm::SmallVector<CXXCtorInitializer *, 4> Initializers; - ID.AddInteger(D->getNumCtorInitializers()); - for (auto Initializer : D->inits()) { - if (Initializer->isWritten()) { - ++NumCtorInits; - Initializers.push_back(Initializer); - } - } - for (auto Initializer : Initializers) { - AddStmt(Initializer->getInit()); - } - - Inherited::VisitCXXConstructorDecl(D); - } - - void VisitCXXConversionDecl(const CXXConversionDecl *D) { - AddQualType(D->getConversionType()); - Hash.AddBoolean(D->isExplicitSpecified()); - Inherited::VisitCXXConversionDecl(D); - } - - void VisitFieldDecl(const FieldDecl *D) { - Hash.AddBoolean(D->isMutable()); - - const bool isBitField = D->isBitField(); - Hash.AddBoolean(isBitField); - if (isBitField) - AddStmt(D->getBitWidth()); - - AddStmt(D->getInClassInitializer()); - - Inherited::VisitFieldDecl(D); - } - - void VisitTemplateDecl(const TemplateDecl *D) { - AddDecl(D->getTemplatedDecl()); - - auto *Parameters = D->getTemplateParameters(); - ID.AddInteger(Parameters->size()); - for (auto *ND : *Parameters) - AddDecl(ND); - - Inherited::VisitTemplateDecl(D); - } - - void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - Inherited::VisitFunctionTemplateDecl(D); - } - - void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { - const bool hasDefaultArgument = D->hasDefaultArgument(); - Hash.AddBoolean(hasDefaultArgument); - if (hasDefaultArgument) - AddTemplateArgument(D->getDefaultArgument()); - - Inherited::VisitTemplateTypeParmDecl(D); - } - - void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { - AddStmt(D->hasDefaultArgument() ? D->getDefaultArgument() : nullptr); - - Inherited::VisitNonTypeTemplateParmDecl(D); - } - - void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { - const bool hasDefaultArgument = D->hasDefaultArgument(); - Hash.AddBoolean(hasDefaultArgument); - if (hasDefaultArgument) - AddTemplateArgument(D->getDefaultArgument().getArgument()); - - Inherited::VisitTemplateTemplateParmDecl(D); - } - - void VisitCXXRecordDecl(const CXXRecordDecl *D) { - const bool hasDefinition = D->hasDefinition(); - Hash.AddBoolean(hasDefinition); - if (hasDefinition) { - ID.AddInteger(D->getODRHash()); - } - Inherited::VisitCXXRecordDecl(D); - } -}; - - -void ODRHash::AddSubDecl(const Decl *D) { - assert(D && "Expecting non-null pointer."); - AddDecl(D); - ODRDeclVisitor(ID, *this).Visit(D); -} - -void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { - assert(Record && Record->hasDefinition() && - "Expected non-null record to be a definition."); - AddDecl(Record); - - // Filter out sub-Decls which will not be processed in order to get an - // accurate count of Decl's. - llvm::SmallVector<const Decl *, 16> Decls; - for (const Decl *SubDecl : Record->decls()) { - // Ignore implicit Decl's. - if (SubDecl->isImplicit()) { - continue; - } - // Ignore Decl's that are not in the context of the CXXRecordDecl. - if (SubDecl->getDeclContext() != Record) { - continue; - } - Decls.push_back(SubDecl); - } - - ID.AddInteger(Decls.size()); - for (auto SubDecl : Decls) { - AddSubDecl(SubDecl); - } - - ID.AddInteger(Record->getNumBases()); - for (auto base : Record->bases()) { - AddBoolean(base.isVirtual()); - AddQualType(base.getType()); - } - - const ClassTemplateDecl *TD = Record->getDescribedClassTemplate(); - AddBoolean(TD); - if (TD) { - AddTemplateParameterList(TD->getTemplateParameters()); - } -} - -void ODRHash::AddDecl(const Decl *D) { - assert(D && "Expecting non-null pointer."); - auto Result = DeclMap.insert(std::make_pair(D, DeclMap.size())); - ID.AddInteger(Result.first->second); - // On first encounter of a Decl pointer, process it. Every time afterwards, - // only the index value is needed. - if (!Result.second) { - return; - } - - // Unlike the DeclVisitor, this adds a limited amount of information to - // identify the Decl. - ID.AddInteger(D->getKind()); - - // Unlike other places where AddBoolean is used with possibly null pointers, - // the nullness of the following pointers is already encoded with the - // DeclKind value, so there is no ambiguity on what information is added. - if (const auto *ND = dyn_cast<NamedDecl>(D)) { - AddDeclarationName(ND->getDeclName()); - } - - if (const auto *Typedef = dyn_cast<TypedefNameDecl>(D)) { - AddQualType(Typedef->getUnderlyingType()); - } - - if (const auto *Alias = dyn_cast<NamespaceAliasDecl>(D)) { - AddDecl(Alias->getNamespace()); - } -} - -// Process a Type pointer. Add* methods call back into ODRHash while Visit* -// methods process the relevant parts of the Type. -class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> { - typedef TypeVisitor<ODRTypeVisitor> Inherited; - llvm::FoldingSetNodeID &ID; - ODRHash &Hash; - -public: - ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash) - : ID(ID), Hash(Hash) {} - - void AddType(const Type *T) { - Hash.AddType(T); - } - - void AddQualType(QualType T) { - Hash.AddQualType(T); - } - - void AddDecl(Decl *D) { - Hash.AddBoolean(D); - if (D) { - Hash.AddDecl(D); - } - } - - void AddTemplateArgument(TemplateArgument TA) { - Hash.AddTemplateArgument(TA); - } - - void AddStmt(Stmt *S) { - Hash.AddBoolean(S); - if (S) { - Hash.AddStmt(S); - } - } - - void AddNestedNameSpecifier(NestedNameSpecifier *NNS) { - Hash.AddBoolean(NNS); - if (NNS) { - Hash.AddNestedNameSpecifier(NNS); - } - } - void AddIdentiferInfo(const IdentifierInfo *II) { - Hash.AddBoolean(II); - if (II) { - Hash.AddIdentifierInfo(II); - } - } - - void AddTemplateName(TemplateName TN) { - Hash.AddTemplateName(TN); - } - - void VisitQualifiers(Qualifiers Quals) { - ID.AddInteger(Quals.getAsOpaqueValue()); - } - - void Visit(const Type *T) { - ID.AddInteger(T->getTypeClass()); - Inherited::Visit(T); - } - - void VisitType(const Type *T) {} - - void VisitAdjustedType(const AdjustedType *T) { - AddQualType(T->getOriginalType()); - AddQualType(T->getAdjustedType()); - VisitType(T); - } - - void VisitDecayedType(const DecayedType *T) { - AddQualType(T->getDecayedType()); - AddQualType(T->getPointeeType()); - VisitAdjustedType(T); - } - - void VisitArrayType(const ArrayType *T) { - AddQualType(T->getElementType()); - ID.AddInteger(T->getSizeModifier()); - VisitQualifiers(T->getIndexTypeQualifiers()); - VisitType(T); - } - void VisitConstantArrayType(const ConstantArrayType *T) { - T->getSize().Profile(ID); - VisitArrayType(T); - } - - void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - AddStmt(T->getSizeExpr()); - VisitArrayType(T); - } - - void VisitIncompleteArrayType(const IncompleteArrayType *T) { - VisitArrayType(T); - } - - void VisitVariableArrayType(const VariableArrayType *T) { - AddStmt(T->getSizeExpr()); - VisitArrayType(T); - } - - void VisitAtomicType(const AtomicType *T) { - AddQualType(T->getValueType()); - VisitType(T); - } - - void VisitAttributedType(const AttributedType *T) { - ID.AddInteger(T->getAttrKind()); - AddQualType(T->getModifiedType()); - AddQualType(T->getEquivalentType()); - VisitType(T); - } - - void VisitBlockPointerType(const BlockPointerType *T) { - AddQualType(T->getPointeeType()); - VisitType(T); - } - - void VisitBuiltinType(const BuiltinType *T) { - ID.AddInteger(T->getKind()); - VisitType(T); - } - - void VisitComplexType(const ComplexType *T) { - AddQualType(T->getElementType()); - VisitType(T); - } - - void VisitDecltypeType(const DecltypeType *T) { - AddQualType(T->getUnderlyingType()); - AddStmt(T->getUnderlyingExpr()); - VisitType(T); - } - - void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { - AddQualType(T->getElementType()); - AddStmt(T->getSizeExpr()); - VisitType(T); - } - - void VisitFunctionType(const FunctionType *T) { - AddQualType(T->getReturnType()); - T->getExtInfo().Profile(ID); - Hash.AddBoolean(T->isConst()); - Hash.AddBoolean(T->isVolatile()); - Hash.AddBoolean(T->isRestrict()); - VisitType(T); - } - - void VisitFunctionNoProtoType(const FunctionNoProtoType *T) { - VisitFunctionType(T); - } - - void VisitFunctionProtoType(const FunctionProtoType *T) { - ID.AddInteger(T->getNumParams()); - for (auto ParamType : T->getParamTypes()) - AddQualType(ParamType); - - const auto &epi = T->getExtProtoInfo(); - ID.AddInteger(epi.Variadic); - ID.AddInteger(epi.TypeQuals); - ID.AddInteger(epi.RefQualifier); - ID.AddInteger(epi.ExceptionSpec.Type); - - if (epi.ExceptionSpec.Type == EST_Dynamic) { - for (QualType Ex : epi.ExceptionSpec.Exceptions) - AddQualType(Ex); - } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept && - epi.ExceptionSpec.NoexceptExpr) { - AddStmt(epi.ExceptionSpec.NoexceptExpr); - } else if (epi.ExceptionSpec.Type == EST_Uninstantiated || - epi.ExceptionSpec.Type == EST_Unevaluated) { - AddDecl(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); - } - if (epi.ExtParameterInfos) { - for (unsigned i = 0; i != T->getNumParams(); ++i) - ID.AddInteger(epi.ExtParameterInfos[i].getOpaqueValue()); - } - epi.ExtInfo.Profile(ID); - Hash.AddBoolean(epi.HasTrailingReturn); - - VisitFunctionType(T); - } - - void VisitInjectedClassNameType(const InjectedClassNameType *T) { - AddDecl(T->getDecl()); - VisitType(T); - } - - void VisitMemberPointerType(const MemberPointerType *T) { - AddQualType(T->getPointeeType()); - AddType(T->getClass()); - VisitType(T); - } - - void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - AddQualType(T->getPointeeType()); - VisitType(T); - } - - void VisitObjCObjectType(const ObjCObjectType *T) { - QualType Base = T->getBaseType(); - Hash.AddBoolean(Base.getTypePtr() != T); - if (Base.getTypePtr() != T) - AddQualType(Base); - auto TypeArgs = T->getTypeArgsAsWritten(); - ID.AddInteger(TypeArgs.size()); - for (auto TypeArg : TypeArgs) - AddQualType(TypeArg); - ID.AddInteger(T->getNumProtocols()); - for (auto proto : T->quals()) - AddDecl(proto); - ID.AddInteger(T->isKindOfTypeAsWritten()); - VisitType(T); - } - - void VisitObjCInterfaceType(const ObjCInterfaceType *T) { - VisitObjCObjectType(T); - } - - void VisitObjCObjectTypeImpl(const ObjCObjectTypeImpl *T) { - VisitObjCObjectType(T); - } - - void VisitPackExpansionType(const PackExpansionType *T) { - AddQualType(T->getPattern()); - auto NumExpansions = T->getNumExpansions(); - Hash.AddBoolean(NumExpansions.hasValue()); - if (NumExpansions) - ID.AddInteger(*NumExpansions); - VisitType(T); - }; - - void VisitPointerType(const PointerType *T) { - AddQualType(T->getPointeeType()); - VisitType(T); - } - - void VisitReferenceType(const ReferenceType *T) { - AddQualType(T->getPointeeTypeAsWritten()); - VisitType(T); - } - - void VisitLValueReferenceType(const LValueReferenceType *T) { - VisitReferenceType(T); - } - - void VisitRValueReferenceType(const RValueReferenceType *T) { - VisitReferenceType(T); - } - - void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { - AddQualType(T->getReplacementType()); - AddType(T->getReplacedParameter()); - VisitType(T); - } - - void - VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { - AddType(T->getReplacedParameter()); - AddTemplateArgument(T->getArgumentPack()); - VisitType(T); - } - - void VisitTagType(const TagType *T) { - AddDecl(T->getDecl()); - Hash.AddBoolean(T->isBeingDefined()); - VisitType(T); - } - - void VisitEnumType(const EnumType *T) { - AddDecl(T->getDecl()); - VisitTagType(T); - } - - void VisitRecordType(const RecordType *T) { - AddDecl(T->getDecl()); - VisitTagType(T); - } - - void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { - AddTemplateName(T->getTemplateName()); - ID.AddInteger(T->getNumArgs()); - for (auto I = T->begin(), E = T->end(); I != E; ++I) - AddTemplateArgument(*I); - VisitType(T); - } - - void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - ID.AddInteger(T->getDepth()); - ID.AddInteger(T->getIndex()); - Hash.AddBoolean(T->isParameterPack()); - AddDecl(T->getDecl()); - VisitType(T); - } - - void VisitTypedefType(const TypedefType *T) { - AddDecl(T->getDecl()); - VisitType(T); - } - - void VisitTypeOfExprType(const TypeOfExprType *T) { - AddStmt(T->getUnderlyingExpr()); - VisitType(T); - } - - void VisitDependentTypeOfExprType(const DependentTypeOfExprType *T) { - VisitTypeOfExprType(T); - } - - void VisitTypeWithKeyword(const TypeWithKeyword *T) { VisitType(T); } - - void VisitElaboratedType(const ElaboratedType *T) { - ID.AddInteger(T->getKeyword()); - AddNestedNameSpecifier(T->getQualifier()); - AddQualType(T->getNamedType()); - VisitTypeWithKeyword(T); - } - - void VisitUnaryTransformType(const UnaryTransformType *T) { - AddQualType(T->getBaseType()); - ID.AddInteger(T->getUTTKind()); - VisitType(T); - } - - void VisitDependentUnaryTransformType(const DependentUnaryTransformType *T) { - VisitUnaryTransformType(T); - } - - void VisitUnresolvedUsingType(const UnresolvedUsingType *T) { - AddDecl(T->getDecl()); - VisitType(T); - } - - void VisitVectorType(const VectorType *T) { - AddQualType(T->getElementType()); - ID.AddInteger(T->getNumElements()); - ID.AddInteger(T->getVectorKind()); - VisitType(T); - } - - void VisitExtVectorType(const ExtVectorType *T) { VisitVectorType(T); } -}; - -void ODRHash::AddType(const Type *T) { - assert(T && "Expecting non-null pointer."); - auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size())); - ID.AddInteger(Result.first->second); - // On first encounter of a Type pointer, process it. Every time afterwards, - // only the index value is needed. - if (!Result.second) { - return; - } - - ODRTypeVisitor(ID, *this).Visit(T); -} - -void ODRHash::AddQualType(QualType T) { - AddBoolean(T.isNull()); - if (T.isNull()) - return; - SplitQualType split = T.split(); - ID.AddInteger(split.Quals.getAsOpaqueValue()); - AddType(split.Ty); -} - -void ODRHash::AddBoolean(bool Value) { - Bools.push_back(Value); -} Modified: cfe/trunk/lib/AST/StmtProfile.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtProfile.cpp (original) +++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Feb 17 01:19:24 2017 @@ -19,22 +19,20 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" -#include "clang/AST/ODRHash.h" #include "clang/AST/StmtVisitor.h" #include "llvm/ADT/FoldingSet.h" using namespace clang; namespace { class StmtProfiler : public ConstStmtVisitor<StmtProfiler> { - protected: llvm::FoldingSetNodeID &ID; + const ASTContext &Context; bool Canonical; public: - StmtProfiler(llvm::FoldingSetNodeID &ID, bool Canonical) - : ID(ID), Canonical(Canonical) {} - - virtual ~StmtProfiler() {} + StmtProfiler(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + bool Canonical) + : ID(ID), Context(Context), Canonical(Canonical) { } void VisitStmt(const Stmt *S); @@ -43,25 +41,22 @@ namespace { /// \brief Visit a declaration that is referenced within an expression /// or statement. - virtual void VisitDecl(const Decl *D) = 0; + void VisitDecl(const Decl *D); /// \brief Visit a type that is referenced within an expression or /// statement. - virtual void VisitType(QualType T) = 0; + void VisitType(QualType T); /// \brief Visit a name that occurs within an expression or statement. - virtual void VisitName(DeclarationName Name) = 0; - - /// \brief Visit identifiers that are not in Decl's or Type's. - virtual void VisitIdentifierInfo(IdentifierInfo *II) = 0; + void VisitName(DeclarationName Name); /// \brief Visit a nested-name-specifier that occurs within an expression /// or statement. - virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0; + void VisitNestedNameSpecifier(NestedNameSpecifier *NNS); /// \brief Visit a template name that occurs within an expression or /// statement. - virtual void VisitTemplateName(TemplateName Name) = 0; + void VisitTemplateName(TemplateName Name); /// \brief Visit template arguments that occur within an expression or /// statement. @@ -71,127 +66,6 @@ namespace { /// \brief Visit a single template argument. void VisitTemplateArgument(const TemplateArgument &Arg); }; - - class StmtProfilerWithPointers : public StmtProfiler { - const ASTContext &Context; - - public: - StmtProfilerWithPointers(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, bool Canonical) - : StmtProfiler(ID, Canonical), Context(Context) {} - private: - void VisitDecl(const Decl *D) override { - ID.AddInteger(D ? D->getKind() : 0); - - if (Canonical && D) { - if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(D)) { - ID.AddInteger(NTTP->getDepth()); - ID.AddInteger(NTTP->getIndex()); - ID.AddBoolean(NTTP->isParameterPack()); - VisitType(NTTP->getType()); - return; - } - - if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { - // The Itanium C++ ABI uses the type, scope depth, and scope - // index of a parameter when mangling expressions that involve - // function parameters, so we will use the parameter's type for - // establishing function parameter identity. That way, our - // definition of "equivalent" (per C++ [temp.over.link]) is at - // least as strong as the definition of "equivalent" used for - // name mangling. - VisitType(Parm->getType()); - ID.AddInteger(Parm->getFunctionScopeDepth()); - ID.AddInteger(Parm->getFunctionScopeIndex()); - return; - } - - if (const TemplateTypeParmDecl *TTP = - dyn_cast<TemplateTypeParmDecl>(D)) { - ID.AddInteger(TTP->getDepth()); - ID.AddInteger(TTP->getIndex()); - ID.AddBoolean(TTP->isParameterPack()); - return; - } - - if (const TemplateTemplateParmDecl *TTP = - dyn_cast<TemplateTemplateParmDecl>(D)) { - ID.AddInteger(TTP->getDepth()); - ID.AddInteger(TTP->getIndex()); - ID.AddBoolean(TTP->isParameterPack()); - return; - } - } - - ID.AddPointer(D ? D->getCanonicalDecl() : nullptr); - } - - void VisitType(QualType T) override { - if (Canonical) - T = Context.getCanonicalType(T); - - ID.AddPointer(T.getAsOpaquePtr()); - } - - void VisitName(DeclarationName Name) override { - ID.AddPointer(Name.getAsOpaquePtr()); - } - - void VisitIdentifierInfo(IdentifierInfo *II) override { - ID.AddPointer(II); - } - - void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { - if (Canonical) - NNS = Context.getCanonicalNestedNameSpecifier(NNS); - ID.AddPointer(NNS); - } - - void VisitTemplateName(TemplateName Name) override { - if (Canonical) - Name = Context.getCanonicalTemplateName(Name); - - Name.Profile(ID); - } - }; - - class StmtProfilerWithoutPointers : public StmtProfiler { - ODRHash &Hash; - public: - StmtProfilerWithoutPointers(llvm::FoldingSetNodeID &ID, ODRHash &Hash) - : StmtProfiler(ID, false), Hash(Hash) {} - - private: - void VisitType(QualType T) override { - Hash.AddQualType(T); - } - - void VisitName(DeclarationName Name) override { - Hash.AddDeclarationName(Name); - } - void VisitIdentifierInfo(IdentifierInfo *II) override { - ID.AddBoolean(II); - if (II) { - Hash.AddIdentifierInfo(II); - } - } - void VisitDecl(const Decl *D) override { - ID.AddBoolean(D); - if (D) { - Hash.AddDecl(D); - } - } - void VisitTemplateName(TemplateName Name) override { - Hash.AddTemplateName(Name); - } - void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { - ID.AddBoolean(NNS); - if (NNS) { - Hash.AddNestedNameSpecifier(NNS); - } - } - }; } void StmtProfiler::VisitStmt(const Stmt *S) { @@ -979,7 +853,7 @@ void StmtProfiler::VisitOffsetOfExpr(con break; case OffsetOfNode::Identifier: - VisitIdentifierInfo(ON.getFieldName()); + ID.AddPointer(ON.getFieldName()); break; case OffsetOfNode::Base: @@ -987,7 +861,7 @@ void StmtProfiler::VisitOffsetOfExpr(con break; } } - + VisitExpr(S); } @@ -1577,7 +1451,7 @@ StmtProfiler::VisitCXXPseudoDestructorEx if (S->getDestroyedTypeInfo()) VisitType(S->getDestroyedType()); else - VisitIdentifierInfo(S->getDestroyedTypeIdentifier()); + ID.AddPointer(S->getDestroyedTypeIdentifier()); } void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) { @@ -1827,6 +1701,77 @@ void StmtProfiler::VisitObjCAvailability VisitExpr(S); } +void StmtProfiler::VisitDecl(const Decl *D) { + ID.AddInteger(D? D->getKind() : 0); + + if (Canonical && D) { + if (const NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(D)) { + ID.AddInteger(NTTP->getDepth()); + ID.AddInteger(NTTP->getIndex()); + ID.AddBoolean(NTTP->isParameterPack()); + VisitType(NTTP->getType()); + return; + } + + if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { + // The Itanium C++ ABI uses the type, scope depth, and scope + // index of a parameter when mangling expressions that involve + // function parameters, so we will use the parameter's type for + // establishing function parameter identity. That way, our + // definition of "equivalent" (per C++ [temp.over.link]) is at + // least as strong as the definition of "equivalent" used for + // name mangling. + VisitType(Parm->getType()); + ID.AddInteger(Parm->getFunctionScopeDepth()); + ID.AddInteger(Parm->getFunctionScopeIndex()); + return; + } + + if (const TemplateTypeParmDecl *TTP = + dyn_cast<TemplateTypeParmDecl>(D)) { + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getIndex()); + ID.AddBoolean(TTP->isParameterPack()); + return; + } + + if (const TemplateTemplateParmDecl *TTP = + dyn_cast<TemplateTemplateParmDecl>(D)) { + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getIndex()); + ID.AddBoolean(TTP->isParameterPack()); + return; + } + } + + ID.AddPointer(D? D->getCanonicalDecl() : nullptr); +} + +void StmtProfiler::VisitType(QualType T) { + if (Canonical) + T = Context.getCanonicalType(T); + + ID.AddPointer(T.getAsOpaquePtr()); +} + +void StmtProfiler::VisitName(DeclarationName Name) { + ID.AddPointer(Name.getAsOpaquePtr()); +} + +void StmtProfiler::VisitNestedNameSpecifier(NestedNameSpecifier *NNS) { + if (Canonical) + NNS = Context.getCanonicalNestedNameSpecifier(NNS); + ID.AddPointer(NNS); +} + +void StmtProfiler::VisitTemplateName(TemplateName Name) { + if (Canonical) + Name = Context.getCanonicalTemplateName(Name); + + Name.Profile(ID); +} + void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs) { ID.AddInteger(NumArgs); @@ -1876,12 +1821,6 @@ void StmtProfiler::VisitTemplateArgument void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const { - StmtProfilerWithPointers Profiler(ID, Context, Canonical); - Profiler.Visit(this); -} - -void Stmt::ProcessODRHash(llvm::FoldingSetNodeID &ID, - class ODRHash &Hash) const { - StmtProfilerWithoutPointers Profiler(ID, Hash); + StmtProfiler Profiler(ID, Context, Canonical); Profiler.Visit(this); } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 17 01:19:24 2017 @@ -13775,11 +13775,8 @@ void Sema::ActOnTagFinishDefinition(Scop RD->completeDefinition(); } - if (auto *RD = dyn_cast<CXXRecordDecl>(Tag)) { + if (isa<CXXRecordDecl>(Tag)) FieldCollector->FinishClass(); - if (Context.getLangOpts().Modules) - RD->computeODRHash(); - } // Exit this scope of this tag's definition. PopDeclContext(); Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Feb 17 01:19:24 2017 @@ -26,7 +26,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/ODRHash.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" @@ -8893,638 +8892,21 @@ void ASTReader::diagnoseOdrViolations() for (auto *RD : Merge.second) { // Multiple different declarations got merged together; tell the user // where they came from. - if (Merge.first == RD) - continue; - - llvm::SmallVector<std::pair<Decl *, unsigned>, 4> FirstHashes; - llvm::SmallVector<std::pair<Decl *, unsigned>, 4> SecondHashes; - ODRHash Hash; - for (auto D : Merge.first->decls()) { - if (D->isImplicit()) - continue; - Hash.clear(); - Hash.AddSubDecl(D); - FirstHashes.emplace_back(D, Hash.CalculateHash()); - } - for (auto D : RD->decls()) { - if (D->isImplicit()) - continue; - Hash.clear(); - Hash.AddSubDecl(D); - SecondHashes.emplace_back(D, Hash.CalculateHash()); - } - - // Used with err_module_odr_violation_mismatch_decl and - // note_module_odr_violation_mismatch_decl - enum { - EndOfClass, - PublicSpecifer, - PrivateSpecifer, - ProtectedSpecifer, - Friend, - Enum, - StaticAssert, - Typedef, - TypeAlias, - CXXMethod, - CXXConstructor, - CXXDestructor, - CXXConversion, - Field, - Other - } FirstDiffType = Other, - SecondDiffType = Other; - - auto DifferenceSelector = [](Decl *D) { - assert(D && "valid Decl required"); - switch (D->getKind()) { - default: - return Other; - case Decl::AccessSpec: - switch (D->getAccess()) { - case AS_public: - return PublicSpecifer; - case AS_private: - return PrivateSpecifer; - case AS_protected: - return ProtectedSpecifer; - case AS_none: - llvm_unreachable("Invalid access specifier"); - } - case Decl::Friend: - return Friend; - case Decl::Enum: - return Enum; - case Decl::StaticAssert: - return StaticAssert; - case Decl::Typedef: - return Typedef; - case Decl::TypeAlias: - return TypeAlias; - case Decl::CXXMethod: - return CXXMethod; - case Decl::CXXConstructor: - return CXXConstructor; - case Decl::CXXDestructor: - return CXXDestructor; - case Decl::CXXConversion: - return CXXConversion; - case Decl::Field: - return Field; - } - }; - Decl *FirstDecl = nullptr; - Decl *SecondDecl = nullptr; - auto FirstIt = FirstHashes.begin(); - auto SecondIt = SecondHashes.begin(); - - // If there is a diagnoseable difference, FirstDiffType and - // SecondDiffType will not be Other and FirstDecl and SecondDecl will be - // filled in if not EndOfClass. - while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) { - if (FirstIt->second == SecondIt->second) { - ++FirstIt; - ++SecondIt; - continue; - } - - FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first; - SecondDecl = SecondIt == SecondHashes.end() ? nullptr : SecondIt->first; - - FirstDiffType = FirstDecl ? DifferenceSelector(FirstDecl) : EndOfClass; - SecondDiffType = - SecondDecl ? DifferenceSelector(SecondDecl) : EndOfClass; - - break; - } - - if (FirstDiffType == Other || SecondDiffType == Other) { - // Reaching this point means an unexpected Decl was encountered - // or no difference was detected. This causes a generic error - // message to be emitted. - std::string Module = getOwningModuleNameForDiagnostic(Merge.first); - Diag(Merge.first->getLocation(), - diag::err_module_odr_violation_different_definitions) + if (Merge.first != RD) { + // FIXME: Walk the definition, figure out what's different, + // and diagnose that. + if (!Diagnosed) { + std::string Module = getOwningModuleNameForDiagnostic(Merge.first); + Diag(Merge.first->getLocation(), + diag::err_module_odr_violation_different_definitions) << Merge.first << Module.empty() << Module; - - Diag(RD->getLocation(), - diag::note_module_odr_violation_different_definitions) - << getOwningModuleNameForDiagnostic(RD); - Diagnosed = true; - break; - } - - std::string FirstModule = getOwningModuleNameForDiagnostic(Merge.first); - std::string SecondModule = getOwningModuleNameForDiagnostic(RD); - - if (FirstDiffType != SecondDiffType) { - SourceLocation FirstLoc; - SourceRange FirstRange; - if (FirstDiffType == EndOfClass) { - FirstLoc = Merge.first->getBraceRange().getEnd(); - } else { - FirstLoc = FirstIt->first->getLocation(); - FirstRange = FirstIt->first->getSourceRange(); - } - Diag(FirstLoc, diag::err_module_odr_violation_mismatch_decl) - << Merge.first << FirstModule.empty() << FirstModule << FirstRange - << FirstDiffType; - - SourceLocation SecondLoc; - SourceRange SecondRange; - if (SecondDiffType == EndOfClass) { - SecondLoc = RD->getBraceRange().getEnd(); - } else { - SecondLoc = SecondDecl->getLocation(); - SecondRange = SecondDecl->getSourceRange(); - } - Diag(SecondLoc, diag::note_module_odr_violation_mismatch_decl) - << SecondModule << SecondRange << SecondDiffType; - Diagnosed = true; - break; - } - - // Used with err_module_odr_violation_mismatch_decl_diff and - // note_module_odr_violation_mismatch_decl_diff - enum ODRDeclDifference{ - FriendName, - EnumName, - EnumConstantName, - EnumConstantInit, - EnumConstantNoInit, - EnumConstantDiffInit, - EnumNumberOfConstants, - StaticAssertCondition, - StaticAssertMessage, - StaticAssertOnlyMessage, - TypedefName, - MethodName, - MethodStatic, - MethodInline, - MethodConst, - MethodNumParams, - MethodParamName, - MethodParamType, - MethodDefaultArg, - MethodOnlyDefaultArg, - MethodOnlyBody, - MethodBody, - FieldName, - FieldSingleBitField, - FieldMutable, - }; - - // These lambdas have the common portions of the ODR diagnostics. This - // has the same return as Diag(), so addition parameters can be passed - // in with operator<< - auto ODRDiagError = [&Merge, &FirstModule, this]( - SourceLocation Loc, SourceRange Range, ODRDeclDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_mismatch_decl_diff) - << Merge.first << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this]( - SourceLocation Loc, SourceRange Range, ODRDeclDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_mismatch_decl_diff) - << SecondModule << Range << DiffType; - }; - - auto ComputeODRHash = [&Hash](const Stmt* S) { - assert(S); - Hash.clear(); - Hash.AddStmt(S); - return Hash.CalculateHash(); - }; - - // At this point, both decls are of the same type. Dive down deeper into - // the Decl to determine where the first difference is located. - switch (FirstDiffType) { - case Friend: { - FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl); - FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl); - { - auto D = ODRDiagError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendName); - if (TypeSourceInfo *FirstTSI = FirstFriend->getFriendType()) - D << FirstTSI->getType(); - else - D << FirstFriend->getFriendDecl(); - } - { - auto D = ODRDiagNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendName); - if (TypeSourceInfo *SecondTSI = SecondFriend->getFriendType()) - D << SecondTSI->getType(); - else - D << SecondFriend->getFriendDecl(); - } - Diagnosed = true; - break; - } - case Enum: { - EnumDecl *FirstEnum = cast<EnumDecl>(FirstDecl); - EnumDecl *SecondEnum = cast<EnumDecl>(SecondDecl); - if (FirstEnum->getName() != SecondEnum->getName()) { - ODRDiagError(FirstEnum->getLocStart(), FirstEnum->getSourceRange(), - EnumName) - << FirstEnum; - ODRDiagNote(SecondEnum->getLocStart(), SecondEnum->getSourceRange(), - EnumName) - << SecondEnum; - Diagnosed = true; - break; - } - - // Don't use EnumDecl::enumerator_{begin,end}. Decl merging can - // cause the iterators from them to be the same for both Decl's. - EnumDecl::enumerator_iterator FirstEnumIt(FirstEnum->decls_begin()); - EnumDecl::enumerator_iterator FirstEnumEnd(FirstEnum->decls_end()); - EnumDecl::enumerator_iterator SecondEnumIt(SecondEnum->decls_begin()); - EnumDecl::enumerator_iterator SecondEnumEnd(SecondEnum->decls_end()); - int NumElements = 0; - for (; FirstEnumIt != FirstEnumEnd && SecondEnumIt != SecondEnumEnd; - ++FirstEnumIt, ++SecondEnumIt, ++NumElements) { - if (FirstEnumIt->getName() != SecondEnumIt->getName()) { - ODRDiagError(FirstEnumIt->getLocStart(), - FirstEnumIt->getSourceRange(), EnumConstantName) - << *FirstEnumIt << FirstEnum; - ODRDiagNote(SecondEnumIt->getLocStart(), - SecondEnumIt->getSourceRange(), EnumConstantName) - << *SecondEnumIt << SecondEnum; - Diagnosed = true; - break; - } - Expr *FirstInit = FirstEnumIt->getInitExpr(); - Expr *SecondInit = SecondEnumIt->getInitExpr(); - - if (FirstInit && !SecondInit) { - ODRDiagError(FirstEnumIt->getLocStart(), - FirstEnumIt->getSourceRange(), EnumConstantInit) - << *FirstEnumIt << FirstEnum; - - ODRDiagNote(SecondEnumIt->getLocStart(), - SecondEnumIt->getSourceRange(), EnumConstantNoInit) - << *SecondEnumIt << SecondEnum; - Diagnosed = true; - break; - } - - if (!FirstInit && SecondInit) { - ODRDiagError(FirstEnumIt->getLocStart(), - FirstEnumIt->getSourceRange(), EnumConstantNoInit) - << *FirstEnumIt << FirstEnum; - ODRDiagNote(SecondEnumIt->getLocStart(), - SecondEnumIt->getSourceRange(), EnumConstantInit) - << *SecondEnumIt << SecondEnum; - Diagnosed = true; - break; - } - - if (FirstInit == SecondInit) - continue; - - unsigned FirstODRHash = ComputeODRHash(FirstInit); - unsigned SecondODRHash = ComputeODRHash(SecondInit); - - if (FirstODRHash != SecondODRHash) { - ODRDiagError(FirstEnumIt->getLocStart(), - FirstEnumIt->getSourceRange(), EnumConstantDiffInit) - << *FirstEnumIt << FirstEnum; - ODRDiagNote(SecondEnumIt->getLocStart(), - SecondEnumIt->getSourceRange(), EnumConstantDiffInit) - << *SecondEnumIt << SecondEnum; - Diagnosed = true; - break; - } - } - - if (FirstEnumIt == FirstEnumEnd && SecondEnumIt != SecondEnumEnd) { - unsigned FirstEnumSize = NumElements; - unsigned SecondEnumSize = NumElements; - for (; SecondEnumIt != SecondEnumEnd; ++SecondEnumIt) - ++SecondEnumSize; - ODRDiagError(FirstEnum->getLocStart(), FirstEnum->getSourceRange(), - EnumNumberOfConstants) - << FirstEnum << FirstEnumSize; - ODRDiagNote(SecondEnum->getLocStart(), SecondEnum->getSourceRange(), - EnumNumberOfConstants) - << SecondEnum << SecondEnumSize; - Diagnosed = true; - break; - } - - if (FirstEnumIt != FirstEnumEnd && SecondEnumIt == SecondEnumEnd) { - unsigned FirstEnumSize = NumElements; - unsigned SecondEnumSize = NumElements; - for (; FirstEnumIt != FirstEnumEnd; ++FirstEnumIt) - ++FirstEnumSize; - ODRDiagError(FirstEnum->getLocStart(), FirstEnum->getSourceRange(), - EnumNumberOfConstants) - << FirstEnum << FirstEnumSize; - ODRDiagNote(SecondEnum->getLocStart(), SecondEnum->getSourceRange(), - EnumNumberOfConstants) - << SecondEnum << SecondEnumSize; - Diagnosed = true; - break; - } - - break; - } - case StaticAssert: { - StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl); - StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl); - - Expr *FirstExpr = FirstSA->getAssertExpr(); - Expr *SecondExpr = SecondSA->getAssertExpr(); - unsigned FirstODRHash = ComputeODRHash(FirstExpr); - unsigned SecondODRHash = ComputeODRHash(SecondExpr); - if (FirstODRHash != SecondODRHash) { - ODRDiagError(FirstExpr->getLocStart(), FirstExpr->getSourceRange(), - StaticAssertCondition); - ODRDiagNote(SecondExpr->getLocStart(), - SecondExpr->getSourceRange(), StaticAssertCondition); - Diagnosed = true; - break; - } - - StringLiteral *FirstStr = FirstSA->getMessage(); - StringLiteral *SecondStr = SecondSA->getMessage(); - if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) { - SourceLocation FirstLoc, SecondLoc; - SourceRange FirstRange, SecondRange; - if (FirstStr) { - FirstLoc = FirstStr->getLocStart(); - FirstRange = FirstStr->getSourceRange(); - } else { - FirstLoc = FirstSA->getLocStart(); - FirstRange = FirstSA->getSourceRange(); - } - if (SecondStr) { - SecondLoc = SecondStr->getLocStart(); - SecondRange = SecondStr->getSourceRange(); - } else { - SecondLoc = SecondSA->getLocStart(); - SecondRange = SecondSA->getSourceRange(); - } - ODRDiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage) - << (FirstStr == nullptr); - ODRDiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage) - << (SecondStr == nullptr); - Diagnosed = true; - break; - } - - if (FirstStr && SecondStr && - FirstStr->getString() != SecondStr->getString()) { - ODRDiagError(FirstStr->getLocStart(), FirstStr->getSourceRange(), - StaticAssertMessage); - ODRDiagNote(SecondStr->getLocStart(), SecondStr->getSourceRange(), - StaticAssertMessage); Diagnosed = true; - break; - } - break; - } - case Typedef: - case TypeAlias: { - TypedefNameDecl *FirstTD = cast<TypedefNameDecl>(FirstDecl); - TypedefNameDecl *SecondTD = cast<TypedefNameDecl>(SecondDecl); - IdentifierInfo *FirstII = FirstTD->getIdentifier(); - IdentifierInfo *SecondII = SecondTD->getIdentifier(); - if (FirstII && SecondII && FirstII->getName() != SecondII->getName()) { - ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(), - TypedefName) - << (FirstDiffType == TypeAlias) << FirstII; - ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(), - TypedefName) - << (FirstDiffType == TypeAlias) << SecondII; - Diagnosed = true; - break; - } - break; - } - case CXXMethod: - case CXXConstructor: - case CXXConversion: - case CXXDestructor: { - // TODO: Merge with existing method diff logic. - CXXMethodDecl *FirstMD = cast<CXXMethodDecl>(FirstDecl); - CXXMethodDecl *SecondMD = cast<CXXMethodDecl>(SecondDecl); - IdentifierInfo *FirstII = FirstMD->getIdentifier(); - IdentifierInfo *SecondII = SecondMD->getIdentifier(); - if (FirstII && SecondII && FirstII->getName() != SecondII->getName()) { - ODRDiagError(FirstMD->getLocation(), FirstMD->getSourceRange(), - MethodName) - << FirstII; - ODRDiagNote(SecondMD->getLocation(), SecondMD->getSourceRange(), - MethodName) - << SecondII; - Diagnosed = true; - break; - } - - bool FirstStatic = FirstMD->getStorageClass() == SC_Static; - bool SecondStatic = SecondMD->getStorageClass() == SC_Static; - if (FirstStatic != SecondStatic) { - ODRDiagError(FirstMD->getLocation(), FirstMD->getSourceRange(), - MethodStatic) - << FirstMD << FirstStatic; - ODRDiagNote(SecondMD->getLocation(), SecondMD->getSourceRange(), - MethodStatic) - << SecondMD << SecondStatic; - Diagnosed = true; - break; } - bool FirstInline = FirstMD->isInlineSpecified(); - bool SecondInline = SecondMD->isInlineSpecified(); - if (FirstInline != SecondInline) { - ODRDiagError(FirstMD->getLocation(), FirstMD->getSourceRange(), - MethodInline) - << FirstMD << FirstInline; - ODRDiagNote(SecondMD->getLocation(), SecondMD->getSourceRange(), - MethodInline) - << SecondMD << SecondInline; - Diagnosed = true; - break; - } - - bool FirstConst = FirstMD->isConst(); - bool SecondConst = SecondMD->isConst(); - if (FirstConst != SecondConst) { - ODRDiagError(FirstMD->getLocation(), FirstMD->getSourceRange(), - MethodConst) - << FirstMD << FirstInline; - ODRDiagNote(SecondMD->getLocation(), SecondMD->getSourceRange(), - MethodConst) - << SecondMD << SecondInline; - Diagnosed = true; - break; - } - - if (FirstMD->getNumParams() != SecondMD->getNumParams()) { - ODRDiagError(FirstMD->getLocation(), FirstMD->getSourceRange(), - MethodNumParams) - << SecondMD << FirstMD->getNumParams(); - ODRDiagNote(SecondMD->getLocation(), SecondMD->getSourceRange(), - MethodNumParams) - << SecondMD << SecondMD->getNumParams(); - Diagnosed = true; - break; - } - - for (unsigned i = 0, e = FirstMD->getNumParams(); i < e; ++i) { - ParmVarDecl *FirstParam = FirstMD->getParamDecl(i); - ParmVarDecl *SecondParam = SecondMD->getParamDecl(i); - IdentifierInfo *FirstII = FirstParam->getIdentifier(); - IdentifierInfo *SecondII = SecondParam->getIdentifier(); - if ((!FirstII && SecondII) || (FirstII && !SecondII) || - (FirstII && SecondII && - FirstII->getName() != SecondII->getName())) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), MethodParamName) - << SecondMD << i + 1 << (FirstII == nullptr) << FirstII; - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), MethodParamName) - << SecondMD << i + 1 << (SecondII == nullptr) << SecondII; - Diagnosed = true; - break; - } - - if (!Context.hasSameType(FirstParam->getType(), - SecondParam->getType())) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), MethodParamType) - << SecondMD << i + 1 << FirstParam->getType(); - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), MethodParamType) - << SecondMD << i + 1 << SecondParam->getType(); - Diagnosed = true; - break; - } - - Expr *FirstDefaultArg = FirstParam->getDefaultArg(); - Expr *SecondDefaultArg = SecondParam->getDefaultArg(); - if ((!FirstDefaultArg && SecondDefaultArg) || - (FirstDefaultArg && !SecondDefaultArg)) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), MethodOnlyDefaultArg) - << SecondMD << i + 1 << (FirstDefaultArg != nullptr); - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), MethodOnlyDefaultArg) - << SecondMD << i + 1 << (SecondDefaultArg != nullptr); - Diagnosed = true; - break; - } - - if (FirstDefaultArg && SecondDefaultArg) { - unsigned FirstODRHash = ComputeODRHash(FirstDefaultArg); - unsigned SecondODRHash = ComputeODRHash(SecondDefaultArg); - if (FirstODRHash != SecondODRHash) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), MethodDefaultArg) - << SecondMD << i + 1; - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), MethodDefaultArg) - << SecondMD << i + 1; - Diagnosed = true; - break; - } - } - } - - // TODO: Figure out how to diagnose different function bodies. - // Deserialization does not import the second function body. - - break; - } - case Field: { - // TODO: Merge with exising field diff logic. - FieldDecl *FirstField = cast<FieldDecl>(FirstDecl); - FieldDecl *SecondField = cast<FieldDecl>(SecondDecl); - IdentifierInfo *FirstII = FirstField->getIdentifier(); - IdentifierInfo *SecondII = SecondField->getIdentifier(); - if (FirstII->getName() != SecondII->getName()) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldName) - << FirstII; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldName) - << SecondII; - Diagnosed = true; - break; - } - - // This case is handled elsewhere. - if (!Context.hasSameType(FirstField->getType(), - SecondField->getType())) { - break; - } - - bool FirstBitField = FirstField->isBitField(); - bool SecondBitField = SecondField->isBitField(); - if (FirstBitField != SecondBitField) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldSingleBitField) - << FirstII << FirstBitField; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldSingleBitField) - << SecondII << SecondBitField; - Diagnosed = true; - break; - } - - if (FirstBitField && SecondBitField) { - Expr* FirstWidth = FirstField->getBitWidth(); - Expr *SecondWidth = SecondField->getBitWidth(); - unsigned FirstODRHash = ComputeODRHash(FirstWidth); - unsigned SecondODRHash = ComputeODRHash(SecondWidth); - if (FirstODRHash != SecondODRHash) { - ODRDiagError(FirstField->getLocation(), - FirstField->getSourceRange(), FieldSingleBitField) - << FirstII << FirstBitField; - ODRDiagNote(SecondField->getLocation(), - SecondField->getSourceRange(), FieldSingleBitField) - << SecondII << SecondBitField; - Diagnosed = true; - break; - } - } - - bool FirstMutable = FirstField->isMutable(); - bool SecondMutable = SecondField->isMutable(); - if (FirstMutable != SecondMutable) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldMutable) - << FirstII << FirstMutable; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldMutable) - << SecondII << SecondMutable; - Diagnosed = true; - break; - } - break; - } - case Other: - case EndOfClass: - case PublicSpecifer: - case PrivateSpecifer: - case ProtectedSpecifer: - llvm_unreachable("Invalid diff type"); + Diag(RD->getLocation(), + diag::note_module_odr_violation_different_definitions) + << getOwningModuleNameForDiagnostic(RD); } - - if (Diagnosed == true) - continue; - - // Unable to find difference in Decl's, print simple different - // definitions diagnostic. - Diag(Merge.first->getLocation(), - diag::err_module_odr_violation_different_definitions) - << Merge.first << FirstModule.empty() << FirstModule; - Diag(RD->getLocation(), - diag::note_module_odr_violation_different_definitions) - << SecondModule; - Diagnosed = true; } if (!Diagnosed) { Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Feb 17 01:19:24 2017 @@ -1527,7 +1527,6 @@ void ASTDeclReader::ReadCXXDefinitionDat Data.ImplicitCopyAssignmentHasConstParam = Record.readInt(); Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt(); Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt(); - Data.ODRHash = Record.readInt(); Data.NumBases = Record.readInt(); if (Data.NumBases) @@ -1658,7 +1657,6 @@ void ASTDeclReader::MergeDefinitionData( OR_FIELD(HasDeclaredCopyConstructorWithConstParam) OR_FIELD(HasDeclaredCopyAssignmentWithConstParam) MATCH_FIELD(IsLambda) - MATCH_FIELD(ODRHash) #undef OR_FIELD #undef MATCH_FIELD Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Feb 17 01:19:24 2017 @@ -5707,7 +5707,6 @@ void ASTRecordWriter::AddCXXDefinitionDa Record->push_back(Data.ImplicitCopyAssignmentHasConstParam); Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam); Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam); - Record->push_back(Data.ODRHash); // IsLambda bit is already saved. Record->push_back(Data.NumBases); Modified: cfe/trunk/test/Modules/merge-using-decls.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/merge-using-decls.cpp?rev=295427&r1=295426&r2=295427&view=diff ============================================================================== --- cfe/trunk/test/Modules/merge-using-decls.cpp (original) +++ cfe/trunk/test/Modules/merge-using-decls.cpp Fri Feb 17 01:19:24 2017 @@ -37,10 +37,6 @@ template int UseAll<Y>(); // Here, we're instantiating the definition from 'A' and merging the definition // from 'B' into it. -// expected-error@b.h:* {{'D::type' from module 'B' is not present in definition of 'D<T>' in module 'A'}} -// expected-error@b.h:* {{'D::value' from module 'B' is not present in definition of 'D<T>' in module 'A'}} - - // expected-error@b.h:* {{'E::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}} // expected-error@b.h:* {{'E::v' from module 'B' is not present in definition of 'E<T>' in module 'A'}} Removed: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=295426&view=auto ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp (removed) @@ -1,1157 +0,0 @@ -// Clear and create directories -// RUN: rm -rf %t -// RUN: mkdir %t -// RUN: mkdir %t/cache -// RUN: mkdir %t/Inputs - -// Build first header file -// RUN: echo "#define FIRST" >> %t/Inputs/first.h -// RUN: cat %s >> %t/Inputs/first.h - -// Build second header file -// RUN: echo "#define SECOND" >> %t/Inputs/second.h -// RUN: cat %s >> %t/Inputs/second.h - -// Build module map file -// RUN: echo "module first {" >> %t/Inputs/module.map -// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map -// RUN: echo "}" >> %t/Inputs/module.map -// RUN: echo "module second {" >> %t/Inputs/module.map -// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map -// RUN: echo "}" >> %t/Inputs/module.map - -// Run test -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++11 - -#if !defined(FIRST) && !defined(SECOND) -#include "first.h" -#include "second.h" -#endif - -#if defined(FIRST) -struct S1 { - public: -}; -#elif defined(SECOND) -struct S1 { - private: -}; -#else -S1 s1; -// expected-error@first.h:* {{'S1' has different definitions in different modules; first difference is definition in module 'first' found public access specifier}} -// expected-note@second.h:* {{but in 'second' found private access specifier}} -#endif - -#if defined(FIRST) -struct S2Friend2 {}; -struct S2 { - friend S2Friend2; -}; -#elif defined(SECOND) -struct S2Friend1 {}; -struct S2 { - friend S2Friend1; -}; -#else -S2 s2; -// expected-error@first.h:* {{'S2' has different definitions in different modules; first difference is definition in module 'first' found friend 'S2Friend2'}} -// expected-note@second.h:* {{but in 'second' found other friend 'S2Friend1'}} -#endif - -#if defined(FIRST) -template<class> -struct S3Template {}; -struct S3 { - friend S3Template<int>; -}; -#elif defined(SECOND) -template<class> -struct S3Template {}; -struct S3 { - friend S3Template<double>; -}; -#else -S3 s3; -// expected-error@first.h:* {{'S3' has different definitions in different modules; first difference is definition in module 'first' found friend 'S3Template<int>'}} -// expected-note@second.h:* {{but in 'second' found other friend 'S3Template<double>'}} -#endif - -#if defined(FIRST) -struct S4 { - static_assert(1 == 1, "First"); -}; -#elif defined(SECOND) -struct S4 { - static_assert(1 == 1, "Second"); -}; -#else -S4 s4; -// expected-error@first.h:* {{'S4' has different definitions in different modules; first difference is definition in module 'first' found static assert with message}} -// expected-note@second.h:* {{but in 'second' found static assert with different message}} -#endif - -#if defined(FIRST) -struct S5 { - static_assert(1 == 1, "Message"); -}; -#elif defined(SECOND) -struct S5 { - static_assert(2 == 2, "Message"); -}; -#else -S5 s5; -// expected-error@first.h:* {{'S5' has different definitions in different modules; first difference is definition in module 'first' found static assert with condition}} -// expected-note@second.h:* {{but in 'second' found static assert with different condition}} -#endif - -#if defined(FIRST) -struct S6 { - int First(); -}; -#elif defined(SECOND) -struct S6 { - int Second(); -}; -#else -S6 s6; -// expected-error@second.h:* {{'S6::Second' from module 'second' is not present in definition of 'S6' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'Second'}} -#endif - -#if defined(FIRST) -struct S7 { - double foo(); -}; -#elif defined(SECOND) -struct S7 { - int foo(); -}; -#else -S7 s7; -// expected-error@second.h:* {{'S7::foo' from module 'second' is not present in definition of 'S7' in module 'first'}} -// expected-note@first.h:* {{declaration of 'foo' does not match}} -#endif - -#if defined(FIRST) -struct S8 { - void foo(); -}; -#elif defined(SECOND) -struct S8 { - void foo() {} -}; -#else -S8 s8; -// expected-error@first.h:* {{'S8' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S9 { - void foo() { int y = 5; } -}; -#elif defined(SECOND) -struct S9 { - void foo() { int x = 5; } -}; -#else -S9 s9; -// expected-error@first.h:* {{'S9' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S10 { - struct { - int x; - } a; -}; -#elif defined(SECOND) -struct S10 { - struct { - int x; - int y; - } a; -}; -#else -S10 s10; -// expected-error-re@second.h:* {{'S10::(anonymous struct)::y' from module 'second' is not present in definition of 'S10::(anonymous struct at {{.*}}first.h:{{[0-9]*}}:{{[0-9]*}})' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'y'}} - -// expected-error@first.h:* {{'S10' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S11 { - void foo() { int y = sizeof(int); } -}; -#elif defined(SECOND) -struct S11 { - void foo() { int y = sizeof(double); } -}; -#else -S11 s11; -// expected-error@first.h:* {{'S11' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S12 { - int x = sizeof(x); - int y = sizeof(x); -}; -#elif defined(SECOND) -struct S12 { - int x = sizeof(x); - int y = sizeof(y); -}; -#else -S12 s12; -// expected-error@first.h:* {{'S12' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S13 { - template <typename A> void foo(); -}; -#elif defined(SECOND) -struct S13 { - template <typename B> void foo(); -}; -#else -S13 s13; -// expected-error@first.h:* {{'S13' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S14 { - template <typename A, typename B> void foo(); -}; -#elif defined(SECOND) -struct S14 { - template <typename A> void foo(); -}; -#else -S14 s14; -// expected-error@second.h:* {{'S14::foo' from module 'second' is not present in definition of 'S14' in module 'first'}} -// expected-note@first.h:* {{declaration of 'foo' does not match}} -#endif - -#if defined(FIRST) -template <typename T> -struct S15 : T { - void foo() { - int x = __builtin_offsetof(T, first); - } -}; -#elif defined(SECOND) -template <typename T> -struct S15 : T { - void foo() { - int x = __builtin_offsetof(T, second); - } -}; -#else -template <typename T> -void Test15() { - S15<T> s15; -// expected-error@first.h:* {{'S15' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -} -#endif - -#if defined(FIRST) -struct S16 { - template <template<int = 0> class Y> - void foo() { - Y<> y; - } -}; -#elif defined(SECOND) -struct S16 { - template <template<int = 1> class Y> - void foo() { - Y<> y; - } -}; -#else -void TestS16() { - S16 s16; -} -// TODO: Error here -// expected-err or@first.h:* {{'S16' has different definitions in different modules; definition in module 'first' is here}} -// expected-no te@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S17 { - template <template <typename> class T> - static int foo(int a = 1); - template <template <typename> class T, template <typename> class U> - using Q_type = T<int>; -}; -#elif defined(SECOND) -struct S17 { - template <template <typename> class T> - static int foo(int a = 1); - template <template <typename> class T, template <typename> class U> - using Q_type = U<int>; -}; -#else -S17 s17; -// expected-error@second.h:* {{'S17::Q_type' from module 'second' is not present in definition of 'S17' in module 'first'}} -// expected-note@first.h:* {{declaration of 'Q_type' does not match}} -#endif - -#if defined(FIRST) -struct S18 { - enum E { X1 }; -}; -#elif defined(SECOND) -struct S18 { - enum X { X1 }; -}; -#else -S18 s18; -// expected-error@second.h:* {{'S18::X' from module 'second' is not present in definition of 'S18' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'X'}} -#endif - -#if defined(FIRST) -struct S19 { - enum E { X1 }; -}; -#elif defined(SECOND) -struct S19 { - enum E { X1, X2 }; -}; -#else -S19 s19; -// expected-error@first.h:* {{'S19' has different definitions in different modules; first difference is definition in module 'first' found enum 'E' has 1 element}} -// expected-note@second.h:* {{but in 'second' found enum 'E' has 2 elements}} -// expected-error@second.h:* {{'S19::E::X2' from module 'second' is not present in definition of 'S19::E' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'X2'}} -#endif - -#if defined(FIRST) -struct S20 { - enum E { X1 = 1 }; -}; -#elif defined(SECOND) -struct S20 { - enum E { X1 = 5}; -}; -#else -S20 s20; -// expected-error@first.h:* {{'S20' has different definitions in different modules; first difference is definition in module 'first' found element 'X1' in enum 'E' with initializer}} -// expected-note@second.h:* {{but in 'second' found element 'X1' in enum 'E' with different initializer}} -#endif - -#if defined(FIRST) -struct S21 { - void foo() { - label: - ; - } -}; -#elif defined(SECOND) -struct S21 { - void foo() { - ; - } -}; -#else -S21 s21; -// expected-error@first.h:* {{'S21' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S22 { - void foo() { - label_first: - ; - } -}; -#elif defined(SECOND) -struct S22 { - void foo() { - label_second: - ; - } -}; -#else -S22 s22; -// expected-error@first.h:* {{'S22' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S23 { - typedef int a; - typedef char b; -}; -#elif defined(SECOND) -struct S23 { - typedef char a; - typedef int b; -}; -#else -S23 s23; -// expected-error@second.h:* {{'S23::a' from module 'second' is not present in definition of 'S23' in module 'first'}} -// expected-note@first.h:* {{declaration of 'a' does not match}} -// expected-error@second.h:* {{'S23::b' from module 'second' is not present in definition of 'S23' in module 'first'}} -// expected-note@first.h:* {{declaration of 'b' does not match}} -#endif - -#if defined(FIRST) -struct S24 { - inline int foo(); -}; -#elif defined(SECOND) -struct S24 { - int foo(); -}; -#else -S24 s24; -// expected-error@first.h:* {{'S24' has different definitions in different modules; first difference is definition in module 'first' found method 'foo' is inline}} -// expected-note@second.h:* {{but in 'second' found method 'foo' is not inline}} -#endif - -#if defined(FIRST) -struct S25 { - int x; - S25() : x(5) {} -}; -#elif defined(SECOND) -struct S25 { - int x; - S25() {} -}; -#else -S25 s25; -// expected-error@first.h:* {{'S25' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S26 { - int x; - S26() : x(5) {} -}; -#elif defined(SECOND) -struct S26 { - int x; - S26() : x(2) {} -}; -#else -S26 s26; -// expected-error@first.h:* {{'S26' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S27 { - explicit S27(int) {} - S27() {} -}; -#elif defined(SECOND) -struct S27 { - S27(int) {} - S27() {} -}; -#else -S27 s27; -// expected-error@first.h:* {{'S27' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) || defined(SECOND) -struct Base1 { - Base1(); - Base1(int); - Base1(double); -}; - -struct Base2 { - Base2(); - Base2(int); - Base2(double); -}; -#endif - -#if defined(FIRST) -struct S28 : public Base1 {}; -#elif defined(SECOND) -struct S28 : public Base2 {}; -#else -S28 s28; -// expected-error@first.h:* {{'S28' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S29 : virtual Base1 {}; -#elif defined(SECOND) -struct S29 : virtual Base2 {}; -#else -S29 s29; -// expected-error@first.h:* {{'S29' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S30 : public Base1 { - S30() : Base1(1) {} -}; -#elif defined(SECOND) -struct S30 : public Base1 { - S30() : Base1(1.0) {} -}; -#else -S30 s30; -// expected-error@first.h:* {{'S30' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S31 : virtual Base1 { - S31() : Base1(1) {} -}; -#elif defined(SECOND) -struct S31 : virtual Base1 { - S31() : Base1(1.0) {} -}; -#else -S31 s31; -// expected-error@first.h:* {{'S31' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S32 : public Base1, Base2 { - S32() : Base1(1), Base2(1.0) {} -}; -#elif defined(SECOND) -struct S32 : public Base2, Base1 { - S32() : Base2(1), Base1(1.0) {} -}; -#else -S32 s32; -// expected-error@first.h:* {{'S32' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S33 { - S33() : S33(5) {} - S33(int) {int a;} -}; -#elif defined(SECOND) -struct S33 { - S33() : S33(5) {} - S33(int) {} -}; -#else -S33 s33; -// expected-error@first.h:* {{'S33' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S34 { - operator bool(); -}; -#elif defined(SECOND) -struct S34 { - operator int(); -}; -#else -S34 s34; -// expected-error@second.h:* {{'S34::operator int' from module 'second' is not present in definition of 'S34' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'operator int'}} -#endif - -#if defined(FIRST) -struct S35 { - explicit operator bool(); -}; -#elif defined(SECOND) -struct S35 { - operator bool(); -}; -#else -S35 s35; -// expected-error@first.h:* {{'S35' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S36 { - int x : 3; -}; -#elif defined(SECOND) -struct S36 { - int x : 4; -}; -#else -S36 s36; -// expected-error@first.h:* {{'S36' has different definitions in different modules; first difference is definition in module 'first' found bitfield 'x'}} -// expected-note@second.h:* {{but in 'second' found bitfield 'x'}} -#endif - -#if defined(FIRST) -struct S37 { - mutable int x; - int y; -}; -#elif defined(SECOND) -struct S37 { - int x; - mutable int y; -}; -#else -S37 s37; -// expected-error@first.h:* {{'S37' has different definitions in different modules; first difference is definition in module 'first' found mutable 'x'}} -// expected-note@second.h:* {{but in 'second' found non-mutable 'x'}} -#endif - -#if defined(FIRST) -template <class X> -struct S38 { }; -#elif defined(SECOND) -template <class Y> -struct S38 { }; -#else -S38<int> s38; -// expected-error@first.h:* {{'S38' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -template <class X = int> -struct S39 { X x; }; -#elif defined(SECOND) -template <class X = double> -struct S39 { X x; }; -#else -S39<> s39; -// expected-error@first.h:* {{'S39' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -template <int X = 5> -struct S40 { int x = X; }; -#elif defined(SECOND) -template <int X = 7> -struct S40 { int x = X; }; -#else -S40<> s40; -// expected-error@first.h:* {{'S40' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} - -#endif - -#if defined(FIRST) -template <int> class T41a{}; -template <template<int> class T = T41a> -struct S41 {}; -#elif defined(SECOND) -template <int> class T41b{}; -template <template<int> class T = T41b> -struct S41 {}; -#else -using ::S41; -// expected-error@first.h:* {{'S41' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -struct S42 { - void foo() const {} - void bar() {} -}; -#elif defined(SECOND) -struct S42 { - void foo() {} - void bar() const {} -}; -#else -S42 s42; -// expected-error@second.h:* {{'S42::bar' from module 'second' is not present in definition of 'S42' in module 'first'}} -// expected-note@first.h:* {{declaration of 'bar' does not match}} -// expected-error@second.h:* {{'S42::foo' from module 'second' is not present in definition of 'S42' in module 'first'}} -// expected-note@first.h:* {{declaration of 'foo' does not match}} -#endif - -#if defined(FIRST) -struct S43 { - static constexpr int x = 1; - int y = 1; -}; -#elif defined(SECOND) -struct S43 { - int x = 1; - static constexpr int y = 1; -}; -#else -S43 s43; -// expected-error@second.h:* {{'S43::x' from module 'second' is not present in definition of 'S43' in module 'first'}} -// expected-note@first.h:* {{declaration of 'x' does not match}} -// expected-error@second.h:* {{'S43::y' from module 'second' is not present in definition of 'S43' in module 'first'}} -// expected-note@first.h:* {{declaration of 'y' does not match}} -//#endif -#endif - -#if defined(FIRST) -void f44(); -struct S44 { - friend void f44(); -}; -#elif defined(SECOND) -void g44(); -struct S44 { - friend void g44(); -}; -#else -S44 s44; -// expected-error@first.h:* {{'S44' has different definitions in different modules; first difference is definition in module 'first' found friend 'f44'}} -// expected-note@second.h:* {{but in 'second' found other friend 'g44'}} -#endif - -#if defined(FIRST) -struct S45 { int n : 1; }; -#elif defined(SECOND) -struct S45 { int n = 1; }; -#else -S45 s45; -// expected-error@first.h:* {{'S45' has different definitions in different modules; first difference is definition in module 'first' found bitfield 'n'}} -// expected-note@second.h:* {{but in 'second' found field 'n'}} -#endif - -#if defined(FIRST) -struct S46 { - int operator+(int) { return 0; } -}; -#elif defined(SECOND) -struct S46 { - int operator-(int) { return 0; } -}; -#else -S46 s46; -// expected-error@second.h:* {{'S46::operator-' from module 'second' is not present in definition of 'S46' in module 'first'}} -// expected-note@first.h:* {{definition has no member 'operator-'}} -#endif - -#if defined(FIRST) -template <typename T> -struct S47 { - int foo(int); - float foo(float); - int bar(int); - float bar(float); - int x = foo(T()); -}; -#elif defined(SECOND) -template <typename T> -struct S47 { - int foo(int); - float foo(float); - int bar(int); - float bar(float); - int x = bar(T()); -}; -#else -template <typename T> -using S48 = S47<T>; -// expected-error@first.h:* {{'S47' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -template <typename T> -struct S49 { - int operator+(int); - float operator+(float); - int operator-(int); - float operator-(float); - int x = S49() + T(); -}; -#elif defined(SECOND) -template <typename T> -struct S49 { - int operator+(int); - float operator+(float); - int operator-(int); - float operator-(float); - int x = S49() - T(); -}; -#else -template <typename T> -using S50 = S49<T>; -// expected-error@first.h:* {{'S49' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -namespace A51 { - void foo(); -} -struct S51 { - S51() { - A51::foo(); - } -}; -#elif defined(SECOND) -namespace B51 { - void foo(); -} -struct S51 { - S51() { - B51::foo(); - } -}; -#else -S51 s51; -// expected-error@first.h:* {{'S51' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -namespace N52 { - void foo(); -} -struct S52 { - S52() { - N52::foo(); - } -}; -#elif defined(SECOND) -namespace N52 { - void foo(); -} -struct S52 { - S52() { - ::N52::foo(); - } -}; -#else -S52 s52; -// expected-error@first.h:* {{'S52' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -namespace N53 { - struct foo { - static int bar(); - }; - using A = foo; -} -struct S53 { - S53() { - N53::A::bar(); - } -}; -#elif defined(SECOND) -namespace N53 { - struct foo { - static int bar(); - }; - using B = foo; -} -struct S53 { - S53() { - N53::B::bar(); - } -}; -#else -S53 s53; -// expected-error@first.h:* {{'S53' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -namespace N54 { -namespace A { -void foo(); -} -namespace AA = A; -} - -struct S54 { - S54() { - N54::AA::foo(); - } -}; -#elif defined(SECOND) -namespace N54 { -namespace B { -void foo(); -} -namespace BB = B; -} - -struct S54 { - S54() { - N54::BB::foo(); - } -}; -#else -S54 s54; -// expected-error@first.h:* {{'S54' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -namespace N55 { -namespace A { -void foo(); -} -namespace X = A; -} - -struct S55 { - S55() { - N55::X::foo(); - } -}; -#elif defined(SECOND) -namespace N55 { -namespace B { -void foo(); -} -namespace X = B; -} - -struct S55 { - S55() { - N55::X::foo(); - } -}; -#else -S55 s55; -// expected-error@first.h:* {{'S55' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - -#if defined(FIRST) -template<int> struct foo56{}; -template <template<int> class T> -struct S56 {}; -struct S57 { - S56<foo56> a; -}; -#elif defined(SECOND) -template<int> struct bar56{}; -template <template<int> class T> -struct S56 {}; -struct S57 { - S56<bar56> a; -}; -#else -S57 s57; -// expected-error@second.h:* {{'S57::a' from module 'second' is not present in definition of 'S57' in module 'first'}} -// expected-note@first.h:* {{declaration of 'a' does not match}} -#endif - -#if defined(FIRST) -template<int> struct foo58{}; -template <template<int> class T> -struct S58 {}; -struct S59 { - S58<foo58> a; -}; -#elif defined(SECOND) -template<int> struct foo58{}; -template <template<int> class T> -struct S58 {}; -struct S59 { - S58<::foo58> a; -}; -#else -S59 s59; -// expected-error@first.h:* {{'S59' has different definitions in different modules; definition in module 'first' is here}} -// expected-note@second.h:* {{definition in module 'second' is here}} -#endif - - -#if defined(FIRST) -struct S60a {}; - -typedef S60a S61; - -struct S62 { - S61 s61; -}; -#elif defined(SECOND) -struct S60b {}; - -typedef S60b S61; - -struct S62 { - S61 s61; -}; -#else -S62 s62; -// expected-error@second.h:* {{'S62::s61' from module 'second' is not present in definition of 'S62' in module 'first'}} -// expected-note@first.h:* {{declaration of 's61' does not match}} -#endif - -// Don't warn on these cases -#if defined(FIRST) -void f01(int = 0); -struct S01 { friend void f01(int); }; -#elif defined(SECOND) -void f01(int); -struct S01 { friend void f01(int); }; -#else -S01 s01; -#endif - -#if defined(FIRST) -template <template <int> class T> class Wrapper {}; - -template <int N> class SelfReference { - SelfReference(Wrapper<::SelfReference> &R) {} -}; - -struct Xx { - struct Yy { - }; -}; - -Xx::Xx::Xx::Yy yy; - -namespace NNS { -template <typename> struct Foo; -template <template <class> class T = NNS::Foo> -struct NestedNamespaceSpecifier {}; -} -#endif - -#if defined(FIRST) -struct S02 { }; -void S02Construct() { - S02 foo; - S02 bar = foo; - S02 baz(bar); -} -#elif defined(SECOND) -struct S02 { }; -#else -S02 s02; -#endif - -#if defined(FIRST) -template <class> -struct S03 {}; -#elif defined(SECOND) -template <class> -struct S03 {}; -#else -S03<int> s03; -#endif - -#if defined(FIRST) -template <class T> -struct S04 { - T t; -}; -#elif defined(SECOND) -template <class T> -struct S04 { - T t; -}; -#else -S03<int> s04; -#endif - -#if defined(FIRST) -template <class T> -class Wrapper05; -template <class T> -struct S05 { - Wrapper05<T> t; -}; -#elif defined(SECOND) -template <class T> -class Wrapper05; -template <class T> -struct S05 { - Wrapper05<T> t; -}; -#else -template <class T> -class Wrapper05{}; -S05<int> s05; -#endif - -#if defined(FIRST) -enum E06 : int; -struct S06 { - void get(E06) {} -}; -#elif defined(SECOND) -enum E06 : int { A06 }; -struct S06 { - void get(E06) {} -}; -#else -S06 s06; -#endif - -#if defined(FIRST) -struct S07a {}; -struct S07 { - struct S07a *ptr; -}; -#elif defined(SECOND) -struct S07 { - struct S07a *ptr; -}; -#else -S07 s07; -#endif - -#if defined(FIRST) -struct S08a; -struct S08 { - struct S08a *ptr; -}; -#elif defined(SECOND) -struct S08 { - struct S08a *ptr; -}; -#else -S08 s08; -#endif - -// TODO: Error on these cases. -#if defined(FIRST) -enum E { E1 }; -#elif defined(SECOND) -enum E { E1, E2 }; -#else -E e; -#endif - -#if defined(FIRST) -int foo() { return 1; } -#elif defined(SECOND) -int foo() { return 2; } -#else -int number = foo(); -#endif - -// Keep macros contained to one file. -#ifdef FIRST -#undef FIRST -#endif -#ifdef SECOND -#undef SECOND -#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits