r300001 - Revert r298824 & r298816, recommit r298742 & r298754
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 11 18:52:47 PDT 2017
Either this or your other ODR hash change seems to have broken the modules
buildbot:
http://lab.llvm.org:8011/builders/clang-x86_64-linux-selfhost-modules-2/builds/6274/steps/compile.llvm.stage2/logs/stdio
On 11 April 2017 at 15:32, Richard Trieu via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: rtrieu
> Date: Tue Apr 11 17:32:03 2017
> New Revision: 300001
>
> URL: http://llvm.org/viewvc/llvm-project?rev=300001&view=rev
> Log:
> Revert r298824 & r298816, recommit r298742 & r298754
>
> r299989 fixes the underlying issue by waiting long enough to late parsed
> arguments to be processed before doing an calculating the hash.
>
> r298742
> [ODRHash] Add error messages for mismatched parameters in methods.
>
> r298754
> [ODRHash] Add support for array and decayed types.
>
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
> cfe/trunk/lib/AST/ODRHash.cpp
> cfe/trunk/lib/Serialization/ASTReader.cpp
> cfe/trunk/test/Modules/odr_hash.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSerializationKinds.td?rev=300001&r1=300000&r2=300001&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
> (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Tue Apr
> 11 17:32:03 2017
> @@ -146,7 +146,12 @@ def err_module_odr_violation_mismatch_de
> "method %4 is %select{not static|static}5|"
> "method %4 is %select{not volatile|volatile}5|"
> "method %4 is %select{not const|const}5|"
> - "method %4 is %select{not inline|inline}5}3">;
> + "method %4 is %select{not inline|inline}5|"
> + "method %4 that has %5 parameter%s5|"
> + "method %4 with %ordinal5 parameter of type %6%select{| decayed from
> %8}7|"
> + "method %4 with %ordinal5 parameter named %6|"
> + "method %4 with %ordinal5 parameter with %select{no |}6default
> argument|"
> + "method %4 with %ordinal5 parameter with default argument}3">;
>
> def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0'
> found "
> "%select{"
> @@ -166,7 +171,12 @@ def note_module_odr_violation_mismatch_d
> "method %2 is %select{not static|static}3|"
> "method %2 is %select{not volatile|volatile}3|"
> "method %2 is %select{not const|const}3|"
> - "method %2 is %select{not inline|inline}3}1">;
> + "method %2 is %select{not inline|inline}3|"
> + "method %2 that has %3 parameter%s3|"
> + "method %2 with %ordinal3 parameter of type %4%select{| decayed from
> %6}5|"
> + "method %2 with %ordinal3 parameter named %4|"
> + "method %2 with %ordinal3 parameter with %select{no |}4default
> argument|"
> + "method %2 with %ordinal3 parameter with different default argument}1">;
>
> def warn_module_uses_date_time : Warning<
> "%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
>
> Modified: cfe/trunk/lib/AST/ODRHash.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ODRHash.cpp?rev=300001&r1=300000&r2=300001&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ODRHash.cpp (original)
> +++ cfe/trunk/lib/AST/ODRHash.cpp Tue Apr 11 17:32:03 2017
> @@ -169,6 +169,11 @@ public:
> Inherited::VisitValueDecl(D);
> }
>
> + void VisitParmVarDecl(const ParmVarDecl *D) {
> + AddStmt(D->getDefaultArg());
> + Inherited::VisitParmVarDecl(D);
> + }
> +
> void VisitAccessSpecDecl(const AccessSpecDecl *D) {
> ID.AddInteger(D->getAccess());
> Inherited::VisitAccessSpecDecl(D);
> @@ -202,6 +207,12 @@ public:
> Hash.AddBoolean(D->isPure());
> Hash.AddBoolean(D->isDeletedAsWritten());
>
> + ID.AddInteger(D->param_size());
> +
> + for (auto *Param : D->parameters()) {
> + Hash.AddSubDecl(Param);
> + }
> +
> Inherited::VisitFunctionDecl(D);
> }
>
> @@ -315,6 +326,14 @@ public:
> }
> }
>
> + void AddQualType(QualType T) {
> + Hash.AddQualType(T);
> + }
> +
> + void VisitQualifiers(Qualifiers Quals) {
> + ID.AddInteger(Quals.getAsOpaqueValue());
> + }
> +
> void Visit(const Type *T) {
> ID.AddInteger(T->getTypeClass());
> Inherited::Visit(T);
> @@ -322,11 +341,92 @@ public:
>
> void VisitType(const Type *T) {}
>
> + void VisitAdjustedType(const AdjustedType *T) {
> + AddQualType(T->getOriginalType());
> + AddQualType(T->getAdjustedType());
> + VisitType(T);
> + }
> +
> + void VisitDecayedType(const DecayedType *T) {
> + AddQualType(T->getDecayedType());
> + AddQualType(T->getPointeeType());
> + VisitAdjustedType(T);
> + }
> +
> + void VisitArrayType(const ArrayType *T) {
> + AddQualType(T->getElementType());
> + ID.AddInteger(T->getSizeModifier());
> + VisitQualifiers(T->getIndexTypeQualifiers());
> + VisitType(T);
> + }
> + void VisitConstantArrayType(const ConstantArrayType *T) {
> + T->getSize().Profile(ID);
> + VisitArrayType(T);
> + }
> +
> + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
> + AddStmt(T->getSizeExpr());
> + VisitArrayType(T);
> + }
> +
> + void VisitIncompleteArrayType(const IncompleteArrayType *T) {
> + VisitArrayType(T);
> + }
> +
> + void VisitVariableArrayType(const VariableArrayType *T) {
> + AddStmt(T->getSizeExpr());
> + VisitArrayType(T);
> + }
> +
> void VisitBuiltinType(const BuiltinType *T) {
> ID.AddInteger(T->getKind());
> VisitType(T);
> }
>
> + void VisitFunctionType(const FunctionType *T) {
> + AddQualType(T->getReturnType());
> + T->getExtInfo().Profile(ID);
> + Hash.AddBoolean(T->isConst());
> + Hash.AddBoolean(T->isVolatile());
> + Hash.AddBoolean(T->isRestrict());
> + VisitType(T);
> + }
> +
> + void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
> + VisitFunctionType(T);
> + }
> +
> + void VisitFunctionProtoType(const FunctionProtoType *T) {
> + ID.AddInteger(T->getNumParams());
> + for (auto ParamType : T->getParamTypes())
> + AddQualType(ParamType);
> +
> + const auto &epi = T->getExtProtoInfo();
> + ID.AddInteger(epi.Variadic);
> + ID.AddInteger(epi.TypeQuals);
> + ID.AddInteger(epi.RefQualifier);
> + ID.AddInteger(epi.ExceptionSpec.Type);
> +
> + if (epi.ExceptionSpec.Type == EST_Dynamic) {
> + for (QualType Ex : epi.ExceptionSpec.Exceptions)
> + AddQualType(Ex);
> + } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
> + epi.ExceptionSpec.NoexceptExpr) {
> + AddStmt(epi.ExceptionSpec.NoexceptExpr);
> + } else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
> + epi.ExceptionSpec.Type == EST_Unevaluated) {
> + AddDecl(epi.ExceptionSpec.SourceDecl->getCanonicalDecl());
> + }
> + if (epi.ExtParameterInfos) {
> + for (unsigned i = 0; i != T->getNumParams(); ++i)
> + ID.AddInteger(epi.ExtParameterInfos[i].getOpaqueValue());
> + }
> + epi.ExtInfo.Profile(ID);
> + Hash.AddBoolean(epi.HasTrailingReturn);
> +
> + VisitFunctionType(T);
> + }
> +
> void VisitTypedefType(const TypedefType *T) {
> AddDecl(T->getDecl());
> Hash.AddQualType(T->getDecl()->getUnderlyingType());
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTReader.cpp?rev=300001&r1=300000&r2=300001&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Apr 11 17:32:03 2017
> @@ -9282,6 +9282,11 @@ void ASTReader::diagnoseOdrViolations()
> MethodVolatile,
> MethodConst,
> MethodInline,
> + MethodNumberParameters,
> + MethodParameterType,
> + MethodParameterName,
> + MethodParameterSingleDefaultArgument,
> + MethodParameterDifferentDefaultArguments,
> };
>
> // These lambdas have the common portions of the ODR diagnostics.
> This
> @@ -9605,6 +9610,104 @@ void ASTReader::diagnoseOdrViolations()
> Diagnosed = true;
> break;
> }
> +
> + const unsigned FirstNumParameters = FirstMethod->param_size();
> + const unsigned SecondNumParameters = SecondMethod->param_size();
> + if (FirstNumParameters != SecondNumParameters) {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> MethodNumberParameters)
> + << FirstName << FirstNumParameters;
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> MethodNumberParameters)
> + << SecondName << SecondNumParameters;
> + Diagnosed = true;
> + break;
> + }
> +
> + // Need this status boolean to know when break out of the switch.
> + bool ParameterMismatch = false;
> + for (unsigned I = 0; I < FirstNumParameters; ++I) {
> + const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
> + const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);
> +
> + QualType FirstParamType = FirstParam->getType();
> + QualType SecondParamType = SecondParam->getType();
> + if (FirstParamType != SecondParamType) {
> + if (const DecayedType *ParamDecayedType =
> + FirstParamType->getAs<DecayedType>()) {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> MethodParameterType)
> + << FirstName << (I + 1) << FirstParamType << true
> + << ParamDecayedType->getOriginalType();
> + } else {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> MethodParameterType)
> + << FirstName << (I + 1) << FirstParamType << false;
> + }
> +
> + if (const DecayedType *ParamDecayedType =
> + SecondParamType->getAs<DecayedType>()) {
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> MethodParameterType)
> + << SecondName << (I + 1) << SecondParamType << true
> + << ParamDecayedType->getOriginalType();
> + } else {
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> MethodParameterType)
> + << SecondName << (I + 1) << SecondParamType << false;
> + }
> + ParameterMismatch = true;
> + break;
> + }
> +
> + DeclarationName FirstParamName = FirstParam->getDeclName();
> + DeclarationName SecondParamName = SecondParam->getDeclName();
> + if (FirstParamName != SecondParamName) {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> MethodParameterName)
> + << FirstName << (I + 1) << FirstParamName;
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> MethodParameterName)
> + << SecondName << (I + 1) << SecondParamName;
> + ParameterMismatch = true;
> + break;
> + }
> +
> + const Expr* FirstDefaultArg = FirstParam->getDefaultArg();
> + const Expr* SecondDefaultArg = SecondParam->getDefaultArg();
> + if ((!FirstDefaultArg && SecondDefaultArg) ||
> + (FirstDefaultArg && !SecondDefaultArg)) {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> + MethodParameterSingleDefaultArgument)
> + << FirstName << (I + 1) << (FirstDefaultArg != nullptr);
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> + MethodParameterSingleDefaultArgument)
> + << SecondName << (I + 1) << (SecondDefaultArg != nullptr);
> + ParameterMismatch = true;
> + break;
> + }
> +
> + if (ComputeODRHash(FirstDefaultArg) !=
> + ComputeODRHash(SecondDefaultArg)) {
> + ODRDiagError(FirstMethod->getLocation(),
> + FirstMethod->getSourceRange(),
> + MethodParameterDifferentDefaultArguments)
> + << FirstName << (I + 1);
> + ODRDiagNote(SecondMethod->getLocation(),
> + SecondMethod->getSourceRange(),
> + MethodParameterDifferentDefaultArguments)
> + << SecondName << (I + 1);
> + ParameterMismatch = true;
> + break;
> + }
> + }
> +
> + if (ParameterMismatch) {
> + Diagnosed = true;
> + break;
> + }
>
> break;
> }
>
> Modified: cfe/trunk/test/Modules/odr_hash.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/odr_hash.cpp?rev=300001&r1=300000&r2=300001&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/odr_hash.cpp (original)
> +++ cfe/trunk/test/Modules/odr_hash.cpp Tue Apr 11 17:32:03 2017
> @@ -275,6 +275,33 @@ S11 s11;
> // expected-note at first.h:* {{but in 'FirstModule' found field 'x' with a
> different initializer}}
> #endif
>
> +#if defined(FIRST)
> +struct S12 {
> + unsigned x[5];
> +};
> +#elif defined(SECOND)
> +struct S12 {
> + unsigned x[7];
> +};
> +#else
> +S12 s12;
> +// expected-error at first.h:* {{'Field::S12::x' from module 'FirstModule'
> is not present in definition of 'Field::S12' in module 'SecondModule'}}
> +// expected-note at second.h:* {{declaration of 'x' does not match}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S13 {
> + unsigned x[7];
> +};
> +#elif defined(SECOND)
> +struct S13 {
> + double x[7];
> +};
> +#else
> +S13 s13;
> +// expected-error at first.h:* {{'Field::S13::x' from module 'FirstModule'
> is not present in definition of 'Field::S13' in module 'SecondModule'}}
> +// expected-note at second.h:* {{declaration of 'x' does not match}}
> +#endif
> } // namespace Field
>
> namespace Method {
> @@ -403,6 +430,93 @@ S8 s8;
> // expected-note at first.h:* {{but in 'FirstModule' found method 'A' is
> const}}
> #endif
>
> +#if defined(FIRST)
> +struct S9 {
> + void A(int x) {}
> + void A(int x, int y) {}
> +};
> +#elif defined(SECOND)
> +struct S9 {
> + void A(int x, int y) {}
> + void A(int x) {}
> +};
> +#else
> +S9 s9;
> +// expected-error at second.h:* {{'Method::S9' has different definitions in
> different modules; first difference is definition in module 'SecondModule'
> found method 'A' that has 2 parameters}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' that
> has 1 parameter}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S10 {
> + void A(int x) {}
> + void A(float x) {}
> +};
> +#elif defined(SECOND)
> +struct S10 {
> + void A(float x) {}
> + void A(int x) {}
> +};
> +#else
> +S10 s10;
> +// expected-error at second.h:* {{'Method::S10' has different definitions
> in different modules; first difference is definition in module
> 'SecondModule' found method 'A' with 1st parameter of type 'float'}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' with
> 1st parameter of type 'int'}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S11 {
> + void A(int x) {}
> +};
> +#elif defined(SECOND)
> +struct S11 {
> + void A(int y) {}
> +};
> +#else
> +S11 s11;
> +// expected-error at second.h:* {{'Method::S11' has different definitions
> in different modules; first difference is definition in module
> 'SecondModule' found method 'A' with 1st parameter named 'y'}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' with
> 1st parameter named 'x'}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S12 {
> + void A(int x) {}
> +};
> +#elif defined(SECOND)
> +struct S12 {
> + void A(int x = 1) {}
> +};
> +#else
> +S12 s12;
> +// expected-error at second.h:* {{'Method::S12' has different definitions
> in different modules; first difference is definition in module
> 'SecondModule' found method 'A' with 1st parameter with default argument}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' with
> 1st parameter with no default argument}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S13 {
> + void A(int x = 1 + 0) {}
> +};
> +#elif defined(SECOND)
> +struct S13 {
> + void A(int x = 1) {}
> +};
> +#else
> +S13 s13;
> +// expected-error at second.h:* {{'Method::S13' has different definitions
> in different modules; first difference is definition in module
> 'SecondModule' found method 'A' with 1st parameter with default argument}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' with
> 1st parameter with different default argument}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S14 {
> + void A(int x[2]) {}
> +};
> +#elif defined(SECOND)
> +struct S14 {
> + void A(int x[3]) {}
> +};
> +#else
> +S14 s14;
> +// expected-error at second.h:* {{'Method::S14' has different definitions
> in different modules; first difference is definition in module
> 'SecondModule' found method 'A' with 1st parameter of type 'int *' decayed
> from 'int [3]'}}
> +// expected-note at first.h:* {{but in 'FirstModule' found method 'A' with
> 1st parameter of type 'int *' decayed from 'int [2]'}}
> +#endif
> } // namespace Method
>
> // Naive parsing of AST can lead to cycles in processing. Ensure
> @@ -522,71 +636,54 @@ S3 s3;
> #endif
> } // namespace Using
>
> -
> // Interesting cases that should not cause errors. struct S should not
> error
> // while struct T should error at the access specifier mismatch at the
> end.
> +#define ALL_DECLS \
> +public: \
> +private: \
> +protected: \
> + static_assert(1 == 1, "Message"); \
> + static_assert(2 == 2); \
> + \
> + int x; \
> + double y; \
> + \
> + INT z; \
> + \
> + unsigned a : 1; \
> + unsigned b : 2 * 2 + 5 / 2; \
> + \
> + mutable int c = sizeof(x + y); \
> + \
> + void method() {} \
> + static void static_method() {} \
> + virtual void virtual_method() {} \
> + virtual void pure_virtual_method() = 0; \
> + inline void inline_method() {} \
> + void volatile_method() volatile {} \
> + void const_method() const {} \
> + \
> + typedef int typedef_int; \
> + using using_int = int; \
> + \
> + void method_one_arg(int x) {} \
> + void method_one_arg_default_argument(int x = 5 + 5) {} \
> + void method_decayed_type(int x[5]) {} \
> + \
> + int constant_arr[5]; \
> + \
> + double last_decl;
> +
> namespace AllDecls {
> #if defined(FIRST)
> typedef int INT;
> struct S {
> - public:
> - private:
> - protected:
> -
> - static_assert(1 == 1, "Message");
> - static_assert(2 == 2);
> -
> - int x;
> - double y;
> -
> - INT z;
> -
> - unsigned a : 1;
> - unsigned b : 2*2 + 5/2;
> -
> - mutable int c = sizeof(x + y);
> -
> - void method() {}
> - static void static_method() {}
> - virtual void virtual_method() {}
> - virtual void pure_virtual_method() = 0;
> - inline void inline_method() {}
> - void volatile_method() volatile {}
> - void const_method() const {}
> -
> - typedef int typedef_int;
> - using using_int = int;
> + ALL_DECLS
> };
> #elif defined(SECOND)
> typedef int INT;
> struct S {
> - public:
> - private:
> - protected:
> -
> - static_assert(1 == 1, "Message");
> - static_assert(2 == 2);
> -
> - int x;
> - double y;
> -
> - INT z;
> -
> - unsigned a : 1;
> - unsigned b : 2 * 2 + 5 / 2;
> -
> - mutable int c = sizeof(x + y);
> -
> - void method() {}
> - static void static_method() {}
> - virtual void virtual_method() {}
> - virtual void pure_virtual_method() = 0;
> - inline void inline_method() {}
> - void volatile_method() volatile {}
> - void const_method() const {}
> -
> - typedef int typedef_int;
> - using using_int = int;
> + ALL_DECLS
> };
> #else
> S *s;
> @@ -595,66 +692,14 @@ S *s;
> #if defined(FIRST)
> typedef int INT;
> struct T {
> - public:
> - private:
> - protected:
> -
> - static_assert(1 == 1, "Message");
> - static_assert(2 == 2);
> -
> - int x;
> - double y;
> -
> - INT z;
> -
> - unsigned a : 1;
> - unsigned b : 2 * 2 + 5 / 2;
> -
> - mutable int c = sizeof(x + y);
> -
> - void method() {}
> - static void static_method() {}
> - virtual void virtual_method() {}
> - virtual void pure_virtual_method() = 0;
> - inline void inline_method() {}
> - void volatile_method() volatile {}
> - void const_method() const {}
> -
> - typedef int typedef_int;
> - using using_int = int;
> + ALL_DECLS
>
> private:
> };
> #elif defined(SECOND)
> typedef int INT;
> struct T {
> - public:
> - private:
> - protected:
> -
> - static_assert(1 == 1, "Message");
> - static_assert(2 == 2);
> -
> - int x;
> - double y;
> -
> - INT z;
> -
> - unsigned a : 1;
> - unsigned b : 2 * 2 + 5 / 2;
> -
> - mutable int c = sizeof(x + y);
> -
> - void method() {}
> - static void static_method() {}
> - virtual void virtual_method() {}
> - virtual void pure_virtual_method() = 0;
> - inline void inline_method() {}
> - void volatile_method() volatile {}
> - void const_method() const {}
> -
> - typedef int typedef_int;
> - using using_int = int;
> + ALL_DECLS
>
> public:
> };
> @@ -944,6 +989,22 @@ T t;
> #endif
> } // namespace StructWithForwardDeclarationNoDefinition
>
> +namespace LateParsedDefaultArgument {
> +#if defined(FIRST)
> +template <typename T>
> +struct S {
> + struct R {
> + void foo(T x = 0) {}
> + };
> +};
> +#elif defined(SECOND)
> +#else
> +void run() {
> + S<int>::R().foo();
> +}
> +#endif
> +}
> +
> // Keep macros contained to one file.
> #ifdef FIRST
> #undef FIRST
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170411/7b77cf99/attachment-0001.html>
More information about the cfe-commits
mailing list