Yup, that looks like my fault, again. Thanks, Greg, for the test case. It's very similar to the final test in odr_hash.cc, which I thought I had fixed.
On Wed, Apr 12, 2017 at 8:09 AM, Greg Bedwell <gregbedw...@gmail.com> wrote: > We're seeing the same assertion failing in our internal testing (I've not > bisected to a specific change yet though, but it seems likely it's the same > thing as in the log from the modules bot). Here's a reduced example that > triggers it: > > $ cat 2.h > // ============================================ > template <typename alpha> struct Bravo { > void charlie(bool delta = false) {} > }; > typedef Bravo<char> echo; > echo foxtrot; > // ============================================ > > $ clang.exe -x c++-header 2.h > Assertion failed: !hasUninstantiatedDefaultArg() && "Default argument is > not yet instantiated!", file C:\llvm\tools\clang\lib\AST\Decl.cpp, line > 2424 > > -Greg > > > > On 12 April 2017 at 02:52, Richard Smith via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> 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-selfhos >> t-modules-2/builds/6274/steps/compile.llvm.stage2/logs/stdio >> >> On 11 April 2017 at 15:32, Richard Trieu via cfe-commits < >> cfe-commits@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&r >>> 2=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/ODRHas >>> h.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/Serializat >>> ion/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/o >>> dr_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@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@first.h:* {{'Field::S12::x' from module >>> 'FirstModule' is not present in definition of 'Field::S12' in module >>> 'SecondModule'}} >>> +// expected-note@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@first.h:* {{'Field::S13::x' from module >>> 'FirstModule' is not present in definition of 'Field::S13' in module >>> 'SecondModule'}} >>> +// expected-note@second.h:* {{declaration of 'x' does not match}} >>> +#endif >>> } // namespace Field >>> >>> namespace Method { >>> @@ -403,6 +430,93 @@ S8 s8; >>> // expected-note@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@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@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@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@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@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@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@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@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@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@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@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@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@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