I'm hitting the same issue as well. Please let me know if there is anything I can do to get this fixed quickly.
/Eric On Wed, Jan 3, 2018 at 5:20 PM, Richard Trieu via cfe-commits < cfe-commits@lists.llvm.org> wrote: > 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/ODRHas >> h.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/Serializat >> ion/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(PendingFunctionOdrMe >> rgeFailures); >> + 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/Serializat >> ion/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/Serializat >> ion/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 > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits