Seems to be working now. Thank you!
On Thu, Jan 11, 2018 at 9:46 PM, Richard Trieu <rtr...@google.com> wrote: > Hi Vedant and Eric, > > Please retry after r322350. I suspect an interaction between templates > and friend functions is causing this issue. This revision disables hashing > for friend functions for now. > > Richard > > On Thu, Jan 11, 2018 at 3:34 PM, Eric Fiselier <e...@efcs.ca> wrote: > >> 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-s >>>> tage2-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-s >>>> tage2-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&r >>>> 2=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.c >>>> pp?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/o >>>> dr_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