r293611 - Revert r293585 "Add better ODR checking for modules."
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 31 00:24:41 PST 2017
Author: sammccall
Date: Tue Jan 31 02:24:40 2017
New Revision: 293611
URL: http://llvm.org/viewvc/llvm-project?rev=293611&view=rev
Log:
Revert r293585 "Add better ODR checking for modules."
We're seeing what we believe are false positives. (It's hard to tell with the
available diagnostics, and I'm not sure how to reduce them yet).
I'll send Richard reproduction details offline.
djasper/chandlerc suggested this should be a warning for now, to make rolling it
out feasible.
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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Jan 31 02:24:40 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=293610&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/ODRHash.h (original)
+++ cfe/trunk/include/clang/AST/ODRHash.h (removed)
@@ -1,80 +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);
-
- // Add AST nodes that need to be processes. Some nodes are processed
- // immediately while others are queued and processed later.
- 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);
-
- // Reset the object for reuse.
- void clear();
-
- // Processes any unvisited nodes in Pointers and computes the final hash
- // value.
- unsigned CalculateHash();
-
- // 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Tue Jan 31 02:24:40 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Tue Jan 31 02:24:40 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt (original)
+++ cfe/trunk/lib/AST/CMakeLists.txt Tue Jan 31 02:24:40 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Jan 31 02:24:40 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=293610&view=auto
==============================================================================
--- cfe/trunk/lib/AST/ODRHash.cpp (original)
+++ cfe/trunk/lib/AST/ODRHash.cpp (removed)
@@ -1,892 +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;
-
-// This method adds more information that AddDecl does.
-void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
- assert(Record && Record->hasDefinition() &&
- "Expected non-null record to be a definition.");
- AddDecl(Record);
-
- // Additional information that is not needed in AddDecl. Do not move this
- // to ODRTypeVisitor.
- 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());
- }
-}
-
-// 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;
- }
-}
-
-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()) {
- AddDecl(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());
- 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 VisitDecl(const Decl *D) {
- if (!D) {
- return;
- }
- if (D->isImplicit()) {
- return;
- }
- if (D->isInvalidDecl()) {
- return;
- }
- ID.AddInteger(D->getKind());
- Hash.AddBoolean(D->hasAttrs());
-
- if (auto *DC = dyn_cast<DeclContext>(D)) {
- llvm::SmallVector<const Decl *, 16> Decls;
- for (const Decl* D : DC->decls()) {
- if (!D->isImplicit()) {
- Decls.push_back(D);
- }
- }
- ID.AddInteger(Decls.size());
- for (auto SubDecl : Decls) {
- AddDecl(SubDecl);
- }
- }
-
- 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());
-
- 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) {
- AddStmt(D->getBody());
-
- 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 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) {
- ODRDeclVisitor(ID, *this).Visit(D);
- }
-}
-
-// 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 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 VisitType(const Type *T) { ID.AddInteger(T->getTypeClass()); }
-
- 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) {
- AddQualType(T->getInjectedSpecializationType());
- AddDecl(T->getDecl());
- VisitType(T);
- }
-
- void VisitMemberPointerType(const MemberPointerType *T) {
- AddQualType(T->getPointeeType());
- Visit(T->getClass());
- VisitType(T);
- }
-
- void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
- AddQualType(T->getPointeeType());
- VisitType(T);
- }
-
- void VisitObjCObjectType(const ObjCObjectType *T) {
- QualType Base = T->getBaseType();
- const bool SameType = Base.getTypePtr() == T;
- Hash.AddBoolean(SameType);
- if (!SameType) {
- 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());
- AddQualType(QualType(T->getReplacedParameter(), 0));
- VisitType(T);
- }
-
- void
- VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
- AddQualType(QualType(T->getReplacedParameter(), 0));
- 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) {
- 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Jan 31 02:24:40 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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 31 02:24:40 2017
@@ -13705,11 +13705,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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Jan 31 02:24:40 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"
@@ -8885,638 +8884,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.AddDecl(D);
- FirstHashes.emplace_back(D, Hash.CalculateHash());
- }
- for (auto D : RD->decls()) {
- if (D->isImplicit())
- continue;
- Hash.clear();
- Hash.AddDecl(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 (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 (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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Jan 31 02:24:40 2017
@@ -1521,7 +1521,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)
@@ -1652,7 +1651,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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jan 31 02:24:40 2017
@@ -5699,7 +5699,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=293611&r1=293610&r2=293611&view=diff
==============================================================================
--- cfe/trunk/test/Modules/merge-using-decls.cpp (original)
+++ cfe/trunk/test/Modules/merge-using-decls.cpp Tue Jan 31 02:24:40 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 at b.h:* {{'D::type' from module 'B' is not present in definition of 'D<T>' in module 'A'}}
-// expected-error at b.h:* {{'D::value' from module 'B' is not present in definition of 'D<T>' in module 'A'}}
-
-
// expected-error at b.h:* {{'E::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
// expected-error at 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=293610&view=auto
==============================================================================
--- cfe/trunk/test/Modules/odr_hash.cpp (original)
+++ cfe/trunk/test/Modules/odr_hash.cpp (removed)
@@ -1,1077 +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 at first.h:* {{'S1' has different definitions in different modules; first difference is definition in module 'first' found public access specifier}}
-// expected-note at 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 at first.h:* {{'S2' has different definitions in different modules; first difference is definition in module 'first' found friend 'S2Friend2'}}
-// expected-note at 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 at first.h:* {{'S3' has different definitions in different modules; first difference is definition in module 'first' found friend 'S3Template<int>'}}
-// expected-note at 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 at first.h:* {{'S4' has different definitions in different modules; first difference is definition in module 'first' found static assert with message}}
-// expected-note at 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 at first.h:* {{'S5' has different definitions in different modules; first difference is definition in module 'first' found static assert with condition}}
-// expected-note at 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 at second.h:* {{'S6::Second' from module 'second' is not present in definition of 'S6' in module 'first'}}
-// expected-note at 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 at second.h:* {{'S7::foo' from module 'second' is not present in definition of 'S7' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S8' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S9' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at 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 at first.h:* {{definition has no member 'y'}}
-
-// expected-error at first.h:* {{'S10' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S11' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S12' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S13' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S14::foo' from module 'second' is not present in definition of 'S14' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S15' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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;
-}
-// expected-error at first.h:* {{'S16' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S17::Q_type' from module 'second' is not present in definition of 'S17' in module 'first'}}
-// expected-note at 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 at second.h:* {{'S18::X' from module 'second' is not present in definition of 'S18' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S19' has different definitions in different modules; first difference is definition in module 'first' found enum 'E' has 1 element}}
-// expected-note at second.h:* {{but in 'second' found enum 'E' has 2 elements}}
-// expected-error at second.h:* {{'S19::E::X2' from module 'second' is not present in definition of 'S19::E' in module 'first'}}
-// expected-note at 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 at 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 at 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 at first.h:* {{'S21' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S22' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S23::a' from module 'second' is not present in definition of 'S23' in module 'first'}}
-// expected-note at first.h:* {{declaration of 'a' does not match}}
-// expected-error at second.h:* {{'S23::b' from module 'second' is not present in definition of 'S23' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S24' has different definitions in different modules; first difference is definition in module 'first' found method 'foo' is inline}}
-// expected-note at 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 at first.h:* {{'S25' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S26' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S27' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S28' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S29' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S30' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S31' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S32' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S33' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S34::operator int' from module 'second' is not present in definition of 'S34' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S35' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S36' has different definitions in different modules; first difference is definition in module 'first' found bitfield 'x'}}
-// expected-note at 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 at first.h:* {{'S37' has different definitions in different modules; first difference is definition in module 'first' found mutable 'x'}}
-// expected-note at 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 at first.h:* {{'S38' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S39' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S40' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S41' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S42::bar' from module 'second' is not present in definition of 'S42' in module 'first'}}
-// expected-note at first.h:* {{declaration of 'bar' does not match}}
-// expected-error at second.h:* {{'S42::foo' from module 'second' is not present in definition of 'S42' in module 'first'}}
-// expected-note at 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 at second.h:* {{'S43::x' from module 'second' is not present in definition of 'S43' in module 'first'}}
-// expected-note at first.h:* {{declaration of 'x' does not match}}
-// expected-error at second.h:* {{'S43::y' from module 'second' is not present in definition of 'S43' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S44' has different definitions in different modules; first difference is definition in module 'first' found friend 'f44'}}
-// expected-note at 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 at first.h:* {{'S45' has different definitions in different modules; first difference is definition in module 'first' found bitfield 'n'}}
-// expected-note at 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 at second.h:* {{'S46::operator-' from module 'second' is not present in definition of 'S46' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S47' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S49' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S51' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S52' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S53' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S54' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at first.h:* {{'S55' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at 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 at second.h:* {{'S57::a' from module 'second' is not present in definition of 'S57' in module 'first'}}
-// expected-note at 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 at first.h:* {{'S59' has different definitions in different modules; definition in module 'first' is here}}
-// expected-note at second.h:* {{definition in module 'second' is here}}
-#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
-
-// Keep macros contained to one file.
-#ifdef FIRST
-#undef FIRST
-#endif
-#ifdef SECOND
-#undef SECOND
-#endif
More information about the cfe-commits
mailing list