Vedant, I'm looking into it.
On Wed, Jan 3, 2018 at 11:12 AM, Vedant Kumar <v...@apple.com> wrote: > Oops, the build log was too big to attach. Resending with just the bot > link, then: > http://lab.llvm.org:8080/green/view/Experimental/job/ > clang-stage2-coverage-R/2193/consoleText > > vedant > > On Jan 3, 2018, at 11:09 AM, Vedant Kumar <v...@apple.com> wrote: > > Hi Richard, > > This commit is causing an unexpected build failure in the stage2 > modules-enabled coverage bot. I've attached the build log. Here's the error: > > [3685/3899] > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/bin/clang++ > -DGTEST_HAS_RTTI=0 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS > -D__STDC_LIMIT_MACROS -Itools/lld/COFF > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF > > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/include > -Itools/lld/include -I/usr/include/libxml2 -Iinclude > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include > -fPIC -fvisibility-inlines-hidden -Werror=date-time > -Werror=unguarded-availability-new -std=c++11 -fmodules > -fmodules-cache-path=/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/clang-build/module.cache > -fcxx-modules -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual > -Wmissing-field-initializers -pedantic -Wno-long-long > -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor > -Wstring-conversion -fcolor-diagnostics > -fprofile-instr-generate='/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/clang-build/profiles/%6m.profraw' > -fcoverage-mapping -O3 -DNDEBUG -fno-exceptions -fno-rtti -MMD -MT > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o -MF > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o.d -o > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o -c > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/PDB.cpp > FAILED: tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/bin/clang++ > -DGTEST_HAS_RTTI=0 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS > -D__STDC_LIMIT_MACROS -Itools/lld/COFF > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF > > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/include > -Itools/lld/include -I/usr/include/libxml2 -Iinclude > -I/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include > -fPIC -fvisibility-inlines-hidden -Werror=date-time > -Werror=unguarded-availability-new -std=c++11 -fmodules > -fmodules-cache-path=/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/clang-build/module.cache > -fcxx-modules -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual > -Wmissing-field-initializers -pedantic -Wno-long-long > -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor > -Wstring-conversion -fcolor-diagnostics > -fprofile-instr-generate='/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/clang-build/profiles/%6m.profraw' > -fcoverage-mapping -O3 -DNDEBUG -fno-exceptions -fno-rtti -MMD -MT > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o -MF > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o.d -o > tools/lld/COFF/CMakeFiles/lldCOFF.dir/PDB.cpp.o -c > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/PDB.cpp > In module 'std' imported from > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/Config.h:16: > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/include/c++/v1/list:389:10: > error: 'std::__1::operator==' has different definitions in different > modules; definition in module 'std.list' first difference is function body > bool operator==(const __list_iterator& __x, const __list_iterator& __y) > ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/include/c++/v1/list:389:10: > note: but in 'std.list' found a different body > bool operator==(const __list_iterator& __x, const __list_iterator& __y) > ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/include/c++/v1/list:394:11: > error: 'std::__1::operator!=' has different definitions in different > modules; definition in module 'std.list' first difference is function body > bool operator!=(const __list_iterator& __x, const __list_iterator& __y) > ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/host-compiler/include/c++/v1/list:394:11: > note: but in 'std.list' found a different body > bool operator!=(const __list_iterator& __x, const __list_iterator& __y) > ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > 2 errors generated. > > I'm not sure how to act on this, because it looks like the error is saying > that a definition in 'std.list' is incompatible with itself. > > I've temporarily disabled building with modules enabled on the bot. Could > you take a look? > > thanks, > vedant > > http://lab.llvm.org:8080/green/view/Experimental/job/ > clang-stage2-coverage-R/2193 > > <coverage-build-log.txt> > > > > On Dec 22, 2017, at 4:41 PM, Richard Trieu via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > > Author: rtrieu > Date: Fri Dec 22 16:41:01 2017 > New Revision: 321395 > > URL: http://llvm.org/viewvc/llvm-project?rev=321395&view=rev > Log: > [ODRHash] Support ODR violation detection in functions. > > Extend the hashing to functions, which allows detection of function > definition > mismatches across modules. This is a re-commit of r320230. > > Modified: > cfe/trunk/include/clang/AST/Decl.h > cfe/trunk/include/clang/AST/ODRHash.h > cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td > cfe/trunk/include/clang/Serialization/ASTReader.h > cfe/trunk/lib/AST/Decl.cpp > cfe/trunk/lib/AST/ODRHash.cpp > cfe/trunk/lib/Serialization/ASTReader.cpp > cfe/trunk/lib/Serialization/ASTReaderDecl.cpp > cfe/trunk/lib/Serialization/ASTWriterDecl.cpp > cfe/trunk/test/Modules/odr_hash.cpp > > Modified: cfe/trunk/include/clang/AST/Decl.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/AST/Decl.h?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/AST/Decl.h (original) > +++ cfe/trunk/include/clang/AST/Decl.h Fri Dec 22 16:41:01 2017 > @@ -1759,6 +1759,11 @@ protected: > unsigned IsCopyDeductionCandidate : 1; > > private: > + > + /// Store the ODRHash after first calculation. > + unsigned HasODRHash : 1; > + unsigned ODRHash; > + > /// \brief End part of this FunctionDecl's source range. > /// > /// We could compute the full range in getSourceRange(). However, when > we're > @@ -1841,8 +1846,9 @@ protected: > IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), > IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified), > InstantiationIsPending(false), UsesSEHTry(false), > HasSkippedBody(false), > - WillHaveBody(false), IsCopyDeductionCandidate(false), > - EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {} > + WillHaveBody(false), IsCopyDeductionCandidate(false), > HasODRHash(false), > + ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()), > + DNLoc(NameInfo.getInfo()) {} > > using redeclarable_base = Redeclarable<FunctionDecl>; > > @@ -2439,6 +2445,10 @@ public: > /// returns 0. > unsigned getMemoryFunctionKind() const; > > + /// \brief Returns ODRHash of the function. This value is calculated > and > + /// stored on first call, then the stored value returned on the other > calls. > + unsigned getODRHash(); > + > // Implement isa/cast/dyncast/etc. > static bool classof(const Decl *D) { return classofKind(D->getKind()); } > static bool classofKind(Kind K) { > > Modified: cfe/trunk/include/clang/AST/ODRHash.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/AST/ODRHash.h?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/AST/ODRHash.h (original) > +++ cfe/trunk/include/clang/AST/ODRHash.h Fri Dec 22 16:41:01 2017 > @@ -53,6 +53,10 @@ public: > // more information than the AddDecl class. > void AddCXXRecordDecl(const CXXRecordDecl *Record); > > + // Use this for ODR checking functions between modules. This method > compares > + // more information than the AddDecl class. > + void AddFunctionDecl(const FunctionDecl *Function); > + > // Process SubDecls of the main Decl. This method calls the DeclVisitor > // while AddDecl does not. > void AddSubDecl(const Decl *D); > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ > DiagnosticSerializationKinds.td?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td > (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Fri Dec > 22 16:41:01 2017 > @@ -270,6 +270,29 @@ def note_module_odr_violation_mismatch_d > "friend function %2|" > "}1">; > > +def err_module_odr_violation_function : Error< > + "%q0 has different definitions in different modules; " > + "%select{definition in module '%2'|defined here}1 " > + "first difference is " > + "%select{" > + "return type is %4|" > + "%ordinal4 parameter with name %5|" > + "%ordinal4 parameter with type %5%select{| decayed from %7}6|" > + "%ordinal4 parameter with%select{out|}5 a default argument|" > + "%ordinal4 parameter with a default argument|" > + "function body" > + "}3">; > + > +def note_module_odr_violation_function : Note<"but in '%0' found " > + "%select{" > + "different return type %2|" > + "%ordinal2 parameter with name %3|" > + "%ordinal2 parameter with type %3%select{| decayed from %5}4|" > + "%ordinal2 parameter with%select{out|}3 a default argument|" > + "%ordinal2 parameter with a different default argument|" > + "a different body" > + "}1">; > + > def err_module_odr_violation_mismatch_decl_unknown : Error< > "%q0 %select{with definition in module '%2'|defined here}1 has different > " > "definitions in different modules; first difference is this " > > Modified: cfe/trunk/include/clang/Serialization/ASTReader.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Serialization/ASTReader.h?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Serialization/ASTReader.h (original) > +++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Dec 22 16:41:01 > 2017 > @@ -1092,6 +1092,10 @@ private: > llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, > 2>, 2> > PendingOdrMergeFailures; > > + /// \brief Function definitions in which we found an ODR violation. > + llvm::SmallDenseMap<FunctionDecl *, llvm::SmallVector<FunctionDecl *, > 2>, 2> > + PendingFunctionOdrMergeFailures; > + > /// \brief DeclContexts in which we have diagnosed an ODR violation. > llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures; > > > Modified: cfe/trunk/lib/AST/Decl.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ > Decl.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/AST/Decl.cpp (original) > +++ cfe/trunk/lib/AST/Decl.cpp Fri Dec 22 16:41:01 2017 > @@ -26,6 +26,7 @@ > #include "clang/AST/Expr.h" > #include "clang/AST/ExprCXX.h" > #include "clang/AST/ExternalASTSource.h" > +#include "clang/AST/ODRHash.h" > #include "clang/AST/PrettyPrinter.h" > #include "clang/AST/Redeclarable.h" > #include "clang/AST/Stmt.h" > @@ -3604,6 +3605,25 @@ unsigned FunctionDecl::getMemoryFunction > return 0; > } > > +unsigned FunctionDecl::getODRHash() { > + if (HasODRHash) > + return ODRHash; > + > + if (FunctionDecl *Definition = getDefinition()) { > + if (Definition != this) { > + HasODRHash = true; > + ODRHash = Definition->getODRHash(); > + return ODRHash; > + } > + } > + > + class ODRHash Hash; > + Hash.AddFunctionDecl(this); > + HasODRHash = true; > + ODRHash = Hash.CalculateHash(); > + return ODRHash; > +} > + > //===------------------------------------------------------- > ---------------===// > // FieldDecl Implementation > //===------------------------------------------------------- > ---------------===// > > Modified: cfe/trunk/lib/AST/ODRHash.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ > ODRHash.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/AST/ODRHash.cpp (original) > +++ cfe/trunk/lib/AST/ODRHash.cpp Fri Dec 22 16:41:01 2017 > @@ -466,6 +466,36 @@ void ODRHash::AddCXXRecordDecl(const CXX > } > } > > +void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { > + assert(Function && "Expecting non-null pointer."); > + > + // Skip hashing these kinds of function. > + if (Function->isImplicit()) return; > + if (Function->isDefaulted()) return; > + if (Function->isDeleted()) return; > + if (!Function->hasBody()) return; > + if (!Function->getBody()) return; > + > + // Skip functions that are specializations or in specialization context. > + const DeclContext *DC = Function; > + while (DC) { > + if (isa<ClassTemplateSpecializationDecl>(DC)) return; > + if (auto *F = dyn_cast<FunctionDecl>(DC)) > + if (F->isFunctionTemplateSpecialization()) return; > + DC = DC->getParent(); > + } > + > + AddDecl(Function); > + > + AddQualType(Function->getReturnType()); > + > + ID.AddInteger(Function->param_size()); > + for (auto Param : Function->parameters()) > + AddSubDecl(Param); > + > + AddStmt(Function->getBody()); > +} > + > void ODRHash::AddDecl(const Decl *D) { > assert(D && "Expecting non-null pointer."); > D = D->getCanonicalDecl(); > > Modified: cfe/trunk/lib/Serialization/ASTReader.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ > Serialization/ASTReader.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Dec 22 16:41:01 2017 > @@ -9235,8 +9235,16 @@ void ASTReader::finishPendingActions() { > const FunctionDecl *Defn = nullptr; > if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) { > FD->setLazyBody(PB->second); > - } else > - mergeDefinitionVisibility(const_cast<FunctionDecl*>(Defn), FD); > + } else { > + auto *NonConstDefn = const_cast<FunctionDecl*>(Defn); > + mergeDefinitionVisibility(NonConstDefn, FD); > + > + if (!FD->isLateTemplateParsed() && > + !NonConstDefn->isLateTemplateParsed() && > + FD->getODRHash() != NonConstDefn->getODRHash()) { > + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); > + } > + } > continue; > } > > @@ -9253,7 +9261,8 @@ void ASTReader::finishPendingActions() { > } > > void ASTReader::diagnoseOdrViolations() { > - if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty()) > + if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && > + PendingFunctionOdrMergeFailures.empty()) > return; > > // Trigger the import of the full definition of each class that had any > @@ -9275,6 +9284,20 @@ void ASTReader::diagnoseOdrViolations() > } > } > > + // Trigger the import of functions. > + auto FunctionOdrMergeFailures = std::move( > PendingFunctionOdrMergeFailures); > + PendingFunctionOdrMergeFailures.clear(); > + for (auto &Merge : FunctionOdrMergeFailures) { > + Merge.first->buildLookup(); > + Merge.first->decls_begin(); > + Merge.first->getBody(); > + for (auto &FD : Merge.second) { > + FD->buildLookup(); > + FD->decls_begin(); > + FD->getBody(); > + } > + } > + > // For each declaration from a merged context, check that the canonical > // definition of that context also contains a declaration of the same > // entity. > @@ -9357,13 +9380,35 @@ void ASTReader::diagnoseOdrViolations() > } > } > > - if (OdrMergeFailures.empty()) > + if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty()) > return; > > // Ensure we don't accidentally recursively enter deserialization while > // we're producing our diagnostics. > Deserializing RecursionGuard(this); > > + // Common code for hashing helpers. > + ODRHash Hash; > + auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { > + Hash.clear(); > + Hash.AddQualType(Ty); > + return Hash.CalculateHash(); > + }; > + > + auto ComputeODRHash = [&Hash](const Stmt *S) { > + assert(S); > + Hash.clear(); > + Hash.AddStmt(S); > + return Hash.CalculateHash(); > + }; > + > + auto ComputeSubDeclODRHash = [&Hash](const Decl *D) { > + assert(D); > + Hash.clear(); > + Hash.AddSubDecl(D); > + return Hash.CalculateHash(); > + }; > + > // Issue any pending ODR-failure diagnostics. > for (auto &Merge : OdrMergeFailures) { > // If we've already pointed out a specific problem with this class, > don't > @@ -9411,13 +9456,6 @@ void ASTReader::diagnoseOdrViolations() > << SecondModule << Range << DiffType; > }; > > - ODRHash Hash; > - auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { > - Hash.clear(); > - Hash.AddQualType(Ty); > - return Hash.CalculateHash(); > - }; > - > unsigned FirstNumBases = FirstDD->NumBases; > unsigned FirstNumVBases = FirstDD->NumVBases; > unsigned SecondNumBases = SecondDD->NumBases; > @@ -9520,14 +9558,12 @@ void ASTReader::diagnoseOdrViolations() > if (FirstTemplate && SecondTemplate) { > DeclHashes FirstTemplateHashes; > DeclHashes SecondTemplateHashes; > - ODRHash Hash; > > auto PopulateTemplateParameterHashs = > - [&Hash](DeclHashes &Hashes, const ClassTemplateDecl *TD) { > + [&ComputeSubDeclODRHash](DeclHashes &Hashes, > + const ClassTemplateDecl *TD) { > for (auto *D : TD->getTemplateParameters()->asArray()) { > - Hash.clear(); > - Hash.AddSubDecl(D); > - Hashes.emplace_back(D, Hash.CalculateHash()); > + Hashes.emplace_back(D, ComputeSubDeclODRHash(D)); > } > }; > > @@ -9696,18 +9732,15 @@ void ASTReader::diagnoseOdrViolations() > > DeclHashes FirstHashes; > DeclHashes SecondHashes; > - ODRHash Hash; > > - auto PopulateHashes = [&Hash, FirstRecord](DeclHashes &Hashes, > - CXXRecordDecl *Record) { > + auto PopulateHashes = [&ComputeSubDeclODRHash, FirstRecord]( > + DeclHashes &Hashes, CXXRecordDecl > *Record) { > for (auto *D : Record->decls()) { > // Due to decl merging, the first CXXRecordDecl is the parent of > // Decls in both records. > if (!ODRHash::isWhitelistedDecl(D, FirstRecord)) > continue; > - Hash.clear(); > - Hash.AddSubDecl(D); > - Hashes.emplace_back(D, Hash.CalculateHash()); > + Hashes.emplace_back(D, ComputeSubDeclODRHash(D)); > } > }; > PopulateHashes(FirstHashes, FirstRecord); > @@ -9901,19 +9934,6 @@ void ASTReader::diagnoseOdrViolations() > << SecondModule << Range << DiffType; > }; > > - auto ComputeODRHash = [&Hash](const Stmt* S) { > - assert(S); > - Hash.clear(); > - Hash.AddStmt(S); > - return Hash.CalculateHash(); > - }; > - > - auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { > - Hash.clear(); > - Hash.AddQualType(Ty); > - return Hash.CalculateHash(); > - }; > - > switch (FirstDiffType) { > case Other: > case EndOfClass: > @@ -10488,6 +10508,160 @@ void ASTReader::diagnoseOdrViolations() > << Merge.first; > } > } > + > + // Issue ODR failures diagnostics for functions. > + for (auto &Merge : FunctionOdrMergeFailures) { > + enum ODRFunctionDifference { > + ReturnType, > + ParameterName, > + ParameterType, > + ParameterSingleDefaultArgument, > + ParameterDifferentDefaultArgument, > + FunctionBody, > + }; > + > + FunctionDecl *FirstFunction = Merge.first; > + std::string FirstModule = getOwningModuleNameForDiagnost > ic(FirstFunction); > + > + bool Diagnosed = false; > + for (auto &SecondFunction : Merge.second) { > + > + if (FirstFunction == SecondFunction) > + continue; > + > + std::string SecondModule = > + getOwningModuleNameForDiagnostic(SecondFunction); > + > + auto ODRDiagError = [FirstFunction, &FirstModule, > + this](SourceLocation Loc, SourceRange Range, > + ODRFunctionDifference DiffType) { > + return Diag(Loc, diag::err_module_odr_violation_function) > + << FirstFunction << FirstModule.empty() << FirstModule << > Range > + << DiffType; > + }; > + auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, > + SourceRange Range, > + ODRFunctionDifference > DiffType) { > + return Diag(Loc, diag::note_module_odr_violation_function) > + << SecondModule << Range << DiffType; > + }; > + > + if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) != > + ComputeQualTypeODRHash(SecondFunction->getReturnType())) { > + ODRDiagError(FirstFunction->getReturnTypeSourceRange(). > getBegin(), > + FirstFunction->getReturnTypeSourceRange(), > ReturnType) > + << FirstFunction->getReturnType(); > + ODRDiagNote(SecondFunction->getReturnTypeSourceRange(). > getBegin(), > + SecondFunction->getReturnTypeSourceRange(), > ReturnType) > + << SecondFunction->getReturnType(); > + Diagnosed = true; > + break; > + } > + > + assert(FirstFunction->param_size() == SecondFunction->param_size() > && > + "Merged functions with different number of parameters"); > + > + auto ParamSize = FirstFunction->param_size(); > + bool ParameterMismatch = false; > + for (unsigned I = 0; I < ParamSize; ++I) { > + auto *FirstParam = FirstFunction->getParamDecl(I); > + auto *SecondParam = SecondFunction->getParamDecl(I); > + > + assert(getContext().hasSameType(FirstParam->getType(), > + SecondParam->getType()) && > + "Merged function has different parameter types."); > + > + if (FirstParam->getDeclName() != SecondParam->getDeclName()) { > + ODRDiagError(FirstParam->getLocation(), > FirstParam->getSourceRange(), > + ParameterName) > + << I + 1 << FirstParam->getDeclName(); > + ODRDiagNote(SecondParam->getLocation(), > SecondParam->getSourceRange(), > + ParameterName) > + << I + 1 << SecondParam->getDeclName(); > + ParameterMismatch = true; > + break; > + }; > + > + QualType FirstParamType = FirstParam->getType(); > + QualType SecondParamType = SecondParam->getType(); > + if (FirstParamType != SecondParamType && > + ComputeQualTypeODRHash(FirstParamType) != > + ComputeQualTypeODRHash(SecondParamType)) { > + if (const DecayedType *ParamDecayedType = > + FirstParamType->getAs<DecayedType>()) { > + ODRDiagError(FirstParam->getLocation(), > + FirstParam->getSourceRange(), ParameterType) > + << (I + 1) << FirstParamType << true > + << ParamDecayedType->getOriginalType(); > + } else { > + ODRDiagError(FirstParam->getLocation(), > + FirstParam->getSourceRange(), ParameterType) > + << (I + 1) << FirstParamType << false; > + } > + > + if (const DecayedType *ParamDecayedType = > + SecondParamType->getAs<DecayedType>()) { > + ODRDiagNote(SecondParam->getLocation(), > + SecondParam->getSourceRange(), ParameterType) > + << (I + 1) << SecondParamType << true > + << ParamDecayedType->getOriginalType(); > + } else { > + ODRDiagNote(SecondParam->getLocation(), > + SecondParam->getSourceRange(), ParameterType) > + << (I + 1) << SecondParamType << false; > + } > + ParameterMismatch = true; > + break; > + } > + > + const Expr *FirstInit = FirstParam->getInit(); > + const Expr *SecondInit = SecondParam->getInit(); > + if ((FirstInit == nullptr) != (SecondInit == nullptr)) { > + ODRDiagError(FirstParam->getLocation(), > FirstParam->getSourceRange(), > + ParameterSingleDefaultArgument) > + << (I + 1) << (FirstInit == nullptr) > + << (FirstInit ? FirstInit->getSourceRange() : > SourceRange()); > + ODRDiagNote(SecondParam->getLocation(), > SecondParam->getSourceRange(), > + ParameterSingleDefaultArgument) > + << (I + 1) << (SecondInit == nullptr) > + << (SecondInit ? SecondInit->getSourceRange() : > SourceRange()); > + ParameterMismatch = true; > + break; > + } > + > + if (FirstInit && SecondInit && > + ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { > + ODRDiagError(FirstParam->getLocation(), > FirstParam->getSourceRange(), > + ParameterDifferentDefaultArgument) > + << (I + 1) << FirstInit->getSourceRange(); > + ODRDiagNote(SecondParam->getLocation(), > SecondParam->getSourceRange(), > + ParameterDifferentDefaultArgument) > + << (I + 1) << SecondInit->getSourceRange(); > + ParameterMismatch = true; > + break; > + } > + > + assert(ComputeSubDeclODRHash(FirstParam) == > + ComputeSubDeclODRHash(SecondParam) && > + "Undiagnosed parameter difference."); > + } > + > + if (ParameterMismatch) { > + Diagnosed = true; > + break; > + } > + > + // If no error has been generated before now, assume the problem is > in > + // the body and generate a message. > + ODRDiagError(FirstFunction->getLocation(), > + FirstFunction->getSourceRange(), FunctionBody); > + ODRDiagNote(SecondFunction->getLocation(), > + SecondFunction->getSourceRange(), FunctionBody); > + Diagnosed = true; > + break; > + } > + assert(Diagnosed && "Unable to emit ODR diagnostic."); > + } > } > > void ASTReader::StartedDeserializing() { > > Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ > Serialization/ASTReaderDecl.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Dec 22 16:41:01 2017 > @@ -796,6 +796,9 @@ void ASTDeclReader::VisitFunctionDecl(Fu > FD->setCachedLinkage(Linkage(Record.readInt())); > FD->EndRangeLoc = ReadSourceLocation(); > > + FD->ODRHash = Record.readInt(); > + FD->HasODRHash = true; > + > switch ((FunctionDecl::TemplatedKind)Record.readInt()) { > case FunctionDecl::TK_NonTemplate: > mergeRedeclarable(FD, Redecl); > > Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ > Serialization/ASTWriterDecl.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Dec 22 16:41:01 2017 > @@ -538,6 +538,8 @@ void ASTDeclWriter::VisitFunctionDecl(Fu > Record.push_back(D->getLinkageInternal()); > Record.AddSourceLocation(D->getLocEnd()); > > + Record.push_back(D->getODRHash()); > + > Record.push_back(D->getTemplatedKind()); > switch (D->getTemplatedKind()) { > case FunctionDecl::TK_NonTemplate: > @@ -2072,6 +2074,7 @@ void ASTWriter::WriteDeclAbbrevs() { > Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed > Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage > Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd > + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash > Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind > // This Array slurps the rest of the record. Fortunately we want to > encode > // (nearly) all the remaining (variable number of) fields in the same > way. > > Modified: cfe/trunk/test/Modules/odr_hash.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > Modules/odr_hash.cpp?rev=321395&r1=321394&r2=321395&view=diff > ============================================================ > ================== > --- cfe/trunk/test/Modules/odr_hash.cpp (original) > +++ cfe/trunk/test/Modules/odr_hash.cpp Fri Dec 22 16:41:01 2017 > @@ -557,11 +557,11 @@ S10 s10; > > #if defined(FIRST) > struct S11 { > - void A(int x) {} > + void A(int x); > }; > #elif defined(SECOND) > struct S11 { > - void A(int y) {} > + void A(int y); > }; > #else > S11 s11; > @@ -571,11 +571,11 @@ S11 s11; > > #if defined(FIRST) > struct S12 { > - void A(int x) {} > + void A(int x); > }; > #elif defined(SECOND) > struct S12 { > - void A(int x = 1) {} > + void A(int x = 1); > }; > #else > S12 s12; > @@ -585,11 +585,11 @@ S12 s12; > > #if defined(FIRST) > struct S13 { > - void A(int x = 1 + 0) {} > + void A(int x = 1 + 0); > }; > #elif defined(SECOND) > struct S13 { > - void A(int x = 1) {} > + void A(int x = 1); > }; > #else > S13 s13; > @@ -599,11 +599,11 @@ S13 s13; > > #if defined(FIRST) > struct S14 { > - void A(int x[2]) {} > + void A(int x[2]); > }; > #elif defined(SECOND) > struct S14 { > - void A(int x[3]) {} > + void A(int x[3]); > }; > #else > S14 s14; > @@ -2751,14 +2751,14 @@ namespace DefaultArguments { > template <typename T> > struct S { > struct R { > - void foo(T x = 0) {} > + void foo(T x = 0); > }; > }; > #elif defined(SECOND) > template <typename T> > struct S { > struct R { > - void foo(T x = 1) {} > + void foo(T x = 1); > }; > }; > #else > @@ -2771,13 +2771,13 @@ void run() { > > #if defined(FIRST) > template <typename alpha> struct Bravo { > - void charlie(bool delta = false) {} > + void charlie(bool delta = false); > }; > typedef Bravo<char> echo; > echo foxtrot; > #elif defined(SECOND) > template <typename alpha> struct Bravo { > - void charlie(bool delta = (false)) {} > + void charlie(bool delta = (false)); > }; > typedef Bravo<char> echo; > echo foxtrot; > @@ -2788,6 +2788,142 @@ Bravo<char> golf; > #endif > } // namespace DefaultArguments > > +namespace FunctionDecl { > +#if defined(FIRST) > +struct S1 {}; > +S1 s1a; > +#elif defined(SECOND) > +struct S1 {}; > +#else > +S1 s1; > +#endif > + > +#if defined(FIRST) > +struct S2 { > + S2() = default; > +}; > +S2 s2a = S2(); > +#elif defined(SECOND) > +struct S2 { > + S2() = default; > +}; > +#else > +S2 s2; > +#endif > + > +#if defined(FIRST) > +struct S3 { > + S3() = delete; > +}; > +S3* s3c; > +#elif defined(SECOND) > +struct S3 { > + S3() = delete; > +}; > +#else > +S3* s3; > +#endif > + > +#if defined(FIRST) || defined(SECOND) > +int F1(int x, float y = 2.7) { return 1; } > +#else > +int I1 = F1(1); > +#endif > + > +#if defined(FIRST) > +int F2() { return 1; } > +#elif defined(SECOND) > +double F2() { return 1; } > +#else > +int I2 = F2(); > +// expected-error@-1 {{call to 'F2' is ambiguous}} > +// expected-note@first.h:* {{candidate function}} > +// expected-note@second.h:* {{candidate function}} > +#endif > + > +#if defined(FIRST) > +int F3(float) { return 1; } > +#elif defined(SECOND) > +int F3(double) { return 1; } > +#else > +int I3 = F3(1); > +// expected-error@-1 {{call to 'F3' is ambiguous}} > +// expected-note@first.h:* {{candidate function}} > +// expected-note@second.h:* {{candidate function}} > +#endif > + > +#if defined(FIRST) > +int F4(int x) { return 1; } > +#elif defined(SECOND) > +int F4(int y) { return 1; } > +#else > +int I4 = F4(1); > +// expected-error@second.h:* {{'FunctionDecl::F4' has different > definitions in different modules; definition in module 'SecondModule' first > difference is 1st parameter with name 'y'}} > +// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter > with name 'x'}} > +#endif > + > +#if defined(FIRST) > +int F5(int x) { return 1; } > +#elif defined(SECOND) > +int F5(int x = 1) { return 1; } > +#else > +int I5 = F6(1); > +// expected-error@second.h:* {{'FunctionDecl::F5' has different > definitions in different modules; definition in module 'SecondModule' first > difference is 1st parameter without a default argument}} > +// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter > with a default argument}} > +#endif > + > +#if defined(FIRST) > +int F6(int x = 2) { return 1; } > +#elif defined(SECOND) > +int F6(int x = 1) { return 1; } > +#else > +int I6 = F6(1); > +// expected-error@second.h:* {{'FunctionDecl::F6' has different > definitions in different modules; definition in module 'SecondModule' first > difference is 1st parameter with a default argument}} > +// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter > with a different default argument}} > +#endif > + > +using I = int; > +#if defined(FIRST) > +I F7() { return 0; } > +#elif defined(SECOND) > +int F7() { return 0; } > +#else > +int I7 = F7(); > +// expected-error@second.h:* {{'FunctionDecl::F7' has different > definitions in different modules; definition in module 'SecondModule' first > difference is return type is 'int'}} > +// expected-note@first.h:* {{but in 'FirstModule' found different return > type 'FunctionDecl::I' (aka 'int')}} > +#endif > + > +#if defined(FIRST) > +int F8(int) { return 0; } > +#elif defined(SECOND) > +int F8(I) { return 0; } > +#else > +int I8 = F8(1); > +// expected-error@second.h:* {{'FunctionDecl::F8' has different > definitions in different modules; definition in module 'SecondModule' first > difference is 1st parameter with type 'FunctionDecl::I' (aka 'int')}} > +// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter > with type 'int'}} > +#endif > + > +#if defined(FIRST) > +int F9(int[1]) { return 0; } > +#elif defined(SECOND) > +int F9(int[2]) { return 0; } > +#else > +int I9 = F9(nullptr); > +// expected-error@second.h:* {{'FunctionDecl::F9' has different > definitions in different modules; definition in module 'SecondModule' first > difference is 1st parameter with type 'int *' decayed from 'int [2]'}} > +// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter > with type 'int *' decayed from 'int [1]'}} > +#endif > + > +#if defined(FIRST) > +int F10() { return 1; } > +#elif defined(SECOND) > +int F10() { return 2; } > +#else > +int I10 = F10(); > +#endif > +// expected-error@second.h:* {{'FunctionDecl::F10' has different > definitions in different modules; definition in module 'SecondModule' first > difference is function body}} > +// expected-note@first.h:* {{but in 'FirstModule' found a different > body}} > +} // namespace FunctionDecl > + > // Keep macros contained to one file. > #ifdef FIRST > #undef FIRST > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > > > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits