r333486 - [ODRHash] Support FunctionTemplateDecl in records.

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Tue May 29 18:12:26 PDT 2018


Author: rtrieu
Date: Tue May 29 18:12:26 2018
New Revision: 333486

URL: http://llvm.org/viewvc/llvm-project?rev=333486&view=rev
Log:
[ODRHash] Support FunctionTemplateDecl in records.

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=333486&r1=333485&r2=333486&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Tue May 29 18:12:26 2018
@@ -168,11 +168,11 @@ def err_module_odr_violation_mismatch_de
   "%select{definition in module '%2'|defined here}1 found "
   "%select{end of class|public access specifier|private access specifier|"
   "protected access specifier|static assert|field|method|type alias|typedef|"
-  "data member|friend declaration}3">;
+  "data member|friend declaration|function template}3">;
 def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found "
   "%select{end of class|public access specifier|private access specifier|"
   "protected access specifier|static assert|field|method|type alias|typedef|"
-  "data member|friend declaration}1">;
+  "data member|friend declaration|function template}1">;
 
 def err_module_odr_violation_mismatch_decl_diff : Error<
   "%q0 has different definitions in different modules; first difference is "
@@ -227,6 +227,18 @@ def err_module_odr_violation_mismatch_de
   "friend %select{class|function}4|"
   "friend %4|"
   "friend function %4|"
+  "function template %4 with %5 template parameter%s5|"
+  "function template %4 with %ordinal5 template parameter being a "
+    "%select{type|non-type|template}6 template parameter|"
+  "function template %4 with %ordinal5 template parameter "
+    "%select{with no name|named %7}6|"
+  "function template %4 with %ordinal5 template parameter with "
+    "%select{no |}6default argument|"
+  "function template %4 with %ordinal5 template parameter with "
+    "default argument %6|"
+  "function template %4 with %ordinal5 template parameter with one type|"
+  "function template %4 with %ordinal5 template parameter %select{not |}6"
+    "being a template parameter pack|"
   "}3">;
 
 def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
@@ -280,6 +292,18 @@ def note_module_odr_violation_mismatch_d
   "friend %select{class|function}2|"
   "friend %2|"
   "friend function %2|"
+  "function template %2 with %3 template parameter%s3|"
+  "function template %2 with %ordinal3 template paramter being a "
+    "%select{type|non-type|template}4 template parameter|"
+  "function template %2 with %ordinal3 template parameter "
+    "%select{with no name|named %5}4|"
+  "function template %2 with %ordinal3 template parameter with "
+    "%select{no |}4default argument|"
+  "function template %2 with %ordinal3 template parameter with "
+    "default argument %4|"
+  "function template %2 with %ordinal3 template parameter with different type|"
+  "function template %2 with %ordinal3 template parameter %select{not |}4"
+    "being a template parameter pack|"
   "}1">;
 
 def err_module_odr_violation_function : Error<

Modified: cfe/trunk/lib/AST/ODRHash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=333486&r1=333485&r2=333486&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ODRHash.cpp (original)
+++ cfe/trunk/lib/AST/ODRHash.cpp Tue May 29 18:12:26 2018
@@ -383,6 +383,7 @@ public:
     if (hasDefaultArgument) {
       AddTemplateArgument(D->getDefaultArgument());
     }
+    Hash.AddBoolean(D->isParameterPack());
 
     Inherited::VisitTemplateTypeParmDecl(D);
   }
@@ -395,6 +396,7 @@ public:
     if (hasDefaultArgument) {
       AddStmt(D->getDefaultArgument());
     }
+    Hash.AddBoolean(D->isParameterPack());
 
     Inherited::VisitNonTypeTemplateParmDecl(D);
   }
@@ -407,9 +409,27 @@ public:
     if (hasDefaultArgument) {
       AddTemplateArgument(D->getDefaultArgument().getArgument());
     }
+    Hash.AddBoolean(D->isParameterPack());
 
     Inherited::VisitTemplateTemplateParmDecl(D);
   }
+
+  void VisitTemplateDecl(const TemplateDecl *D) {
+    Hash.AddTemplateParameterList(D->getTemplateParameters());
+
+    Inherited::VisitTemplateDecl(D);
+  }
+
+  void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) {
+    Hash.AddBoolean(D->isMemberSpecialization());
+    Inherited::VisitRedeclarableTemplateDecl(D);
+  }
+
+  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
+    Visit(D->getTemplatedDecl());
+    ID.AddInteger(D->getTemplatedDecl()->getODRHash());
+    Inherited::VisitFunctionTemplateDecl(D);
+  }
 };
 } // namespace
 
@@ -428,6 +448,7 @@ bool ODRHash::isWhitelistedDecl(const De
     case Decl::CXXMethod:
     case Decl::Field:
     case Decl::Friend:
+    case Decl::FunctionTemplate:
     case Decl::StaticAssert:
     case Decl::TypeAlias:
     case Decl::Typedef:

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=333486&r1=333485&r2=333486&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue May 29 18:12:26 2018
@@ -9462,6 +9462,14 @@ void ASTReader::diagnoseOdrViolations()
     return Hash.CalculateHash();
   };
 
+  auto ComputeTemplateParameterListODRHash =
+      [&Hash](const TemplateParameterList *TPL) {
+        assert(TPL);
+        Hash.clear();
+        Hash.AddTemplateParameterList(TPL);
+        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
@@ -9814,6 +9822,7 @@ void ASTReader::diagnoseOdrViolations()
         TypeDef,
         Var,
         Friend,
+        FunctionTemplate,
         Other
       } FirstDiffType = Other,
         SecondDiffType = Other;
@@ -9851,6 +9860,8 @@ void ASTReader::diagnoseOdrViolations()
           return Var;
         case Decl::Friend:
           return Friend;
+        case Decl::FunctionTemplate:
+          return FunctionTemplate;
         }
       };
 
@@ -9937,7 +9948,7 @@ void ASTReader::diagnoseOdrViolations()
 
       // Used with err_module_odr_violation_mismatch_decl_diff and
       // note_module_odr_violation_mismatch_decl_diff
-      enum ODRDeclDifference{
+      enum ODRDeclDifference {
         StaticAssertCondition,
         StaticAssertMessage,
         StaticAssertOnlyMessage,
@@ -9973,6 +9984,13 @@ void ASTReader::diagnoseOdrViolations()
         FriendTypeFunction,
         FriendType,
         FriendFunction,
+        FunctionTemplateDifferentNumberParameters,
+        FunctionTemplateParameterDifferentKind,
+        FunctionTemplateParameterName,
+        FunctionTemplateParameterSingleDefaultArgument,
+        FunctionTemplateParameterDifferentDefaultArgument,
+        FunctionTemplateParameterDifferentType,
+        FunctionTemplatePackParameter,
       };
 
       // These lambdas have the common portions of the ODR diagnostics.  This
@@ -10620,6 +10638,305 @@ void ASTReader::diagnoseOdrViolations()
         Diagnosed = true;
         break;
       }
+      case FunctionTemplate: {
+        FunctionTemplateDecl *FirstTemplate =
+            cast<FunctionTemplateDecl>(FirstDecl);
+        FunctionTemplateDecl *SecondTemplate =
+            cast<FunctionTemplateDecl>(SecondDecl);
+
+        TemplateParameterList *FirstTPL =
+            FirstTemplate->getTemplateParameters();
+        TemplateParameterList *SecondTPL =
+            SecondTemplate->getTemplateParameters();
+
+        if (FirstTPL->size() != SecondTPL->size()) {
+          ODRDiagError(FirstTemplate->getLocation(),
+                       FirstTemplate->getSourceRange(),
+                       FunctionTemplateDifferentNumberParameters)
+              << FirstTemplate << FirstTPL->size();
+          ODRDiagNote(SecondTemplate->getLocation(),
+                      SecondTemplate->getSourceRange(),
+                      FunctionTemplateDifferentNumberParameters)
+              << SecondTemplate  << SecondTPL->size();
+
+          Diagnosed = true;
+          break;
+        }
+
+        bool ParameterMismatch = false;
+        for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
+          NamedDecl *FirstParam = FirstTPL->getParam(i);
+          NamedDecl *SecondParam = SecondTPL->getParam(i);
+
+          if (FirstParam->getKind() != SecondParam->getKind()) {
+            enum {
+              TemplateTypeParameter,
+              NonTypeTemplateParameter,
+              TemplateTemplateParameter,
+            };
+            auto GetParamType = [](NamedDecl *D) {
+              switch (D->getKind()) {
+                default:
+                  llvm_unreachable("Unexpected template parameter type");
+                case Decl::TemplateTypeParm:
+                  return TemplateTypeParameter;
+                case Decl::NonTypeTemplateParm:
+                  return NonTypeTemplateParameter;
+                case Decl::TemplateTemplateParm:
+                  return TemplateTemplateParameter;
+              }
+            };
+
+            ODRDiagError(FirstTemplate->getLocation(),
+                         FirstTemplate->getSourceRange(),
+                         FunctionTemplateParameterDifferentKind)
+                << FirstTemplate << (i + 1) << GetParamType(FirstParam);
+            ODRDiagNote(SecondTemplate->getLocation(),
+                        SecondTemplate->getSourceRange(),
+                        FunctionTemplateParameterDifferentKind)
+                << SecondTemplate << (i + 1) << GetParamType(SecondParam);
+
+            ParameterMismatch = true;
+            break;
+          }
+
+          if (FirstParam->getName() != SecondParam->getName()) {
+            ODRDiagError(FirstTemplate->getLocation(),
+                         FirstTemplate->getSourceRange(),
+                         FunctionTemplateParameterName)
+                << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier()
+                << FirstParam;
+            ODRDiagNote(SecondTemplate->getLocation(),
+                        SecondTemplate->getSourceRange(),
+                        FunctionTemplateParameterName)
+                << SecondTemplate << (i + 1)
+                << (bool)SecondParam->getIdentifier() << SecondParam;
+            ParameterMismatch = true;
+            break;
+          }
+
+          if (isa<TemplateTypeParmDecl>(FirstParam) &&
+              isa<TemplateTypeParmDecl>(SecondParam)) {
+            TemplateTypeParmDecl *FirstTTPD =
+                cast<TemplateTypeParmDecl>(FirstParam);
+            TemplateTypeParmDecl *SecondTTPD =
+                cast<TemplateTypeParmDecl>(SecondParam);
+            bool HasFirstDefaultArgument =
+                FirstTTPD->hasDefaultArgument() &&
+                !FirstTTPD->defaultArgumentWasInherited();
+            bool HasSecondDefaultArgument =
+                SecondTTPD->hasDefaultArgument() &&
+                !SecondTTPD->defaultArgumentWasInherited();
+            if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplateParameterSingleDefaultArgument)
+                  << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplateParameterSingleDefaultArgument)
+                  << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+              ParameterMismatch = true;
+              break;
+            }
+
+            if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+              QualType FirstType = FirstTTPD->getDefaultArgument();
+              QualType SecondType = SecondTTPD->getDefaultArgument();
+              if (ComputeQualTypeODRHash(FirstType) !=
+                  ComputeQualTypeODRHash(SecondType)) {
+                ODRDiagError(FirstTemplate->getLocation(),
+                             FirstTemplate->getSourceRange(),
+                             FunctionTemplateParameterDifferentDefaultArgument)
+                    << FirstTemplate << (i + 1) << FirstType;
+                ODRDiagNote(SecondTemplate->getLocation(),
+                            SecondTemplate->getSourceRange(),
+                            FunctionTemplateParameterDifferentDefaultArgument)
+                    << SecondTemplate << (i + 1) << SecondType;
+                ParameterMismatch = true;
+                break;
+              }
+            }
+
+            if (FirstTTPD->isParameterPack() !=
+                SecondTTPD->isParameterPack()) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplatePackParameter)
+                  << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplatePackParameter)
+                  << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+              ParameterMismatch = true;
+              break;
+            }
+          }
+
+          if (isa<TemplateTemplateParmDecl>(FirstParam) &&
+              isa<TemplateTemplateParmDecl>(SecondParam)) {
+            TemplateTemplateParmDecl *FirstTTPD =
+                cast<TemplateTemplateParmDecl>(FirstParam);
+            TemplateTemplateParmDecl *SecondTTPD =
+                cast<TemplateTemplateParmDecl>(SecondParam);
+
+            TemplateParameterList *FirstTPL =
+                FirstTTPD->getTemplateParameters();
+            TemplateParameterList *SecondTPL =
+                SecondTTPD->getTemplateParameters();
+
+            if (ComputeTemplateParameterListODRHash(FirstTPL) !=
+                ComputeTemplateParameterListODRHash(SecondTPL)) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplateParameterDifferentType)
+                  << FirstTemplate << (i + 1);
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplateParameterDifferentType)
+                  << SecondTemplate << (i + 1);
+              ParameterMismatch = true;
+              break;
+            }
+
+            bool HasFirstDefaultArgument =
+                FirstTTPD->hasDefaultArgument() &&
+                !FirstTTPD->defaultArgumentWasInherited();
+            bool HasSecondDefaultArgument =
+                SecondTTPD->hasDefaultArgument() &&
+                !SecondTTPD->defaultArgumentWasInherited();
+            if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplateParameterSingleDefaultArgument)
+                  << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplateParameterSingleDefaultArgument)
+                  << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+              ParameterMismatch = true;
+              break;
+            }
+
+            if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+              TemplateArgument FirstTA =
+                  FirstTTPD->getDefaultArgument().getArgument();
+              TemplateArgument SecondTA =
+                  SecondTTPD->getDefaultArgument().getArgument();
+              if (ComputeTemplateArgumentODRHash(FirstTA) !=
+                  ComputeTemplateArgumentODRHash(SecondTA)) {
+                ODRDiagError(FirstTemplate->getLocation(),
+                             FirstTemplate->getSourceRange(),
+                             FunctionTemplateParameterDifferentDefaultArgument)
+                    << FirstTemplate << (i + 1) << FirstTA;
+                ODRDiagNote(SecondTemplate->getLocation(),
+                            SecondTemplate->getSourceRange(),
+                            FunctionTemplateParameterDifferentDefaultArgument)
+                    << SecondTemplate << (i + 1) << SecondTA;
+                ParameterMismatch = true;
+                break;
+              }
+            }
+
+            if (FirstTTPD->isParameterPack() !=
+                SecondTTPD->isParameterPack()) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplatePackParameter)
+                  << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplatePackParameter)
+                  << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+              ParameterMismatch = true;
+              break;
+            }
+          }
+
+          if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
+              isa<NonTypeTemplateParmDecl>(SecondParam)) {
+            NonTypeTemplateParmDecl *FirstNTTPD =
+                cast<NonTypeTemplateParmDecl>(FirstParam);
+            NonTypeTemplateParmDecl *SecondNTTPD =
+                cast<NonTypeTemplateParmDecl>(SecondParam);
+
+            QualType FirstType = FirstNTTPD->getType();
+            QualType SecondType = SecondNTTPD->getType();
+            if (ComputeQualTypeODRHash(FirstType) !=
+                ComputeQualTypeODRHash(SecondType)) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplateParameterDifferentType)
+                  << FirstTemplate << (i + 1);
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplateParameterDifferentType)
+                  << SecondTemplate << (i + 1);
+              ParameterMismatch = true;
+              break;
+            }
+
+            bool HasFirstDefaultArgument =
+                FirstNTTPD->hasDefaultArgument() &&
+                !FirstNTTPD->defaultArgumentWasInherited();
+            bool HasSecondDefaultArgument =
+                SecondNTTPD->hasDefaultArgument() &&
+                !SecondNTTPD->defaultArgumentWasInherited();
+            if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplateParameterSingleDefaultArgument)
+                  << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplateParameterSingleDefaultArgument)
+                  << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+              ParameterMismatch = true;
+              break;
+            }
+
+            if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+              Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
+              Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
+              if (ComputeODRHash(FirstDefaultArgument) !=
+                  ComputeODRHash(SecondDefaultArgument)) {
+                ODRDiagError(FirstTemplate->getLocation(),
+                             FirstTemplate->getSourceRange(),
+                             FunctionTemplateParameterDifferentDefaultArgument)
+                    << FirstTemplate << (i + 1) << FirstDefaultArgument;
+                ODRDiagNote(SecondTemplate->getLocation(),
+                            SecondTemplate->getSourceRange(),
+                            FunctionTemplateParameterDifferentDefaultArgument)
+                    << SecondTemplate << (i + 1) << SecondDefaultArgument;
+                ParameterMismatch = true;
+                break;
+              }
+            }
+
+            if (FirstNTTPD->isParameterPack() !=
+                SecondNTTPD->isParameterPack()) {
+              ODRDiagError(FirstTemplate->getLocation(),
+                           FirstTemplate->getSourceRange(),
+                           FunctionTemplatePackParameter)
+                  << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack();
+              ODRDiagNote(SecondTemplate->getLocation(),
+                          SecondTemplate->getSourceRange(),
+                          FunctionTemplatePackParameter)
+                  << SecondTemplate << (i + 1)
+                  << SecondNTTPD->isParameterPack();
+              ParameterMismatch = true;
+              break;
+            }
+          }
+        }
+
+        if (ParameterMismatch) {
+          Diagnosed = true;
+          break;
+        }
+
+        break;
+      }
       }
 
       if (Diagnosed)

Modified: cfe/trunk/test/Modules/odr_hash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=333486&r1=333485&r2=333486&view=diff
==============================================================================
--- cfe/trunk/test/Modules/odr_hash.cpp (original)
+++ cfe/trunk/test/Modules/odr_hash.cpp Tue May 29 18:12:26 2018
@@ -2510,6 +2510,445 @@ Invalid1 i1;
 #undef DECLS
 }  // namespace PointersAndReferences
 
+namespace FunctionTemplate {
+#if defined(FIRST)
+struct S1 {
+  template <int, int> void foo();
+};
+#elif defined(SECOND)
+struct S1 {
+  template <int> void foo();
+};
+#else
+S1 s1;
+// expected-error at first.h:* {{'FunctionTemplate::S1::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S1' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'foo' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+  template <char> void foo();
+};
+#elif defined(SECOND)
+struct S2 {
+  template <int> void foo();
+};
+#else
+S2 s2;
+// expected-error at first.h:* {{'FunctionTemplate::S2::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S2' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'foo' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S3 {
+  template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S3 {
+  template <int y> void foo();
+};
+#else
+S3 s3;
+// expected-error at second.h:* {{'FunctionTemplate::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter named 'y'}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
+#endif
+
+#if defined(FIRST)
+struct S4 {
+  template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S4 {
+  template <int x> void bar();
+};
+#else
+S4 s4;
+// expected-error at first.h:* {{'FunctionTemplate::S4::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S4' in module 'SecondModule'}}
+// expected-note at second.h:* {{definition has no member 'foo'}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+  template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S5 {
+ public:
+  template <int x> void foo();
+};
+#else
+S5 s5;
+// expected-error at second.h:* {{'FunctionTemplate::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template}}
+#endif
+
+#if defined(FIRST)
+struct S6 {
+  template <typename x = int> void foo();
+};
+#elif defined(SECOND)
+struct S6 {
+  template <typename x> void foo();
+};
+#else
+S6 s6;
+// expected-error at second.h:* {{'FunctionTemplate::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S7 {
+  template <typename x = void> void foo();
+};
+#elif defined(SECOND)
+struct S7 {
+  template <typename x = int> void foo();
+};
+#else
+S7 s7;
+// expected-error at second.h:* {{'FunctionTemplate::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
+#endif
+
+#if defined(FIRST)
+template <int>
+struct U8 {};
+struct S8 {
+  template <template<int> class x = U8> void foo();
+};
+#elif defined(SECOND)
+template <int>
+struct T8 {};
+struct S8{
+  template <template<int> class x = T8> void foo();
+};
+#else
+S8 s8;
+// expected-error at second.h:* {{'FunctionTemplate::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'T8'}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'U8'}}
+#endif
+
+#if defined(FIRST)
+template <int>
+struct U9 {};
+struct S9 { S9();
+  template <template<int> class x = U9> void foo();
+};
+#elif defined(SECOND)
+struct S9 { S9();
+  template <template<int> class x> void foo();
+};
+#else
+S9 s9;
+// expected-error at second.h:* {{'FunctionTemplate::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S10 {
+  template <template<int> class x> void foo();
+  template <template<typename> class x> void foo();
+};
+#elif defined(SECOND)
+struct S10 {
+  template <template<typename> class x> void foo();
+  template <template<int> class x> void foo();
+};
+#else
+S10 s10;
+// expected-error at second.h:* {{'FunctionTemplate::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
+#endif
+
+#if defined(FIRST)
+struct S11 {
+  template <template<int> class x> void foo();
+};
+#elif defined(SECOND)
+struct S11 {
+  template <template<int> class> void foo();
+};
+#else
+S11 s11;
+// expected-error at second.h:* {{'FunctionTemplate::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no name}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
+#endif
+
+#if defined(FIRST)
+struct S12 {
+  template <class> void foo();
+  template <class, class> void foo();
+};
+#elif defined(SECOND)
+struct S12 {
+  template <class, class> void foo();
+  template <class> void foo();
+};
+#else
+S12 s12;
+// expected-error at second.h:* {{'FunctionTemplate::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 2 template parameters}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1 template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S13 {
+  template <class = int> void foo();
+};
+#elif defined(SECOND)
+struct S13 {
+  template <class = void> void foo();
+};
+#else
+S13 s13;
+// expected-error at second.h:* {{'FunctionTemplate::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
+#endif
+
+#if defined(FIRST)
+struct S14 {
+  template <class = void> void foo();
+};
+#elif defined(SECOND)
+struct S14 {
+  template <class> void foo();
+};
+#else
+S14 s14;
+// expected-error at second.h:* {{'FunctionTemplate::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S15 {
+  template <class> void foo();
+};
+#elif defined(SECOND)
+struct S15 {
+  template <class = void> void foo();
+};
+#else
+S15 s15;
+// expected-error at second.h:* {{'FunctionTemplate::S15' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
+#endif
+
+#if defined(FIRST)
+struct S16 {
+  template <short> void foo();
+};
+#elif defined(SECOND)
+struct S16 {
+  template <short = 1> void foo();
+};
+#else
+S16 s16;
+// expected-error at second.h:* {{'FunctionTemplate::S16' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
+#endif
+
+#if defined(FIRST)
+struct S17 {
+  template <short = 2> void foo();
+};
+#elif defined(SECOND)
+struct S17 {
+  template <short = 1 + 1> void foo();
+};
+#else
+S17 s17;
+// expected-error at second.h:* {{'FunctionTemplate::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 1 + 1}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 2}}
+#endif
+
+#if defined(FIRST)
+struct S18 {
+  template <short> void foo();
+  template <int> void foo();
+};
+#elif defined(SECOND)
+struct S18 {
+  template <int> void foo();
+  template <short> void foo();
+};
+#else
+S18 s18;
+// expected-error at second.h:* {{'FunctionTemplate::S18' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
+#endif
+
+#if defined(FIRST)
+struct S19 {
+  template <short> void foo();
+  template <short...> void foo();
+};
+#elif defined(SECOND)
+struct S19 {
+  template <short...> void foo();
+  template <short> void foo();
+};
+#else
+S19 s19;
+// expected-error at second.h:* {{'FunctionTemplate::S19' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S20 {
+  template <class> void foo();
+  template <class...> void foo();
+};
+#elif defined(SECOND)
+struct S20 {
+  template <class...> void foo();
+  template <class> void foo();
+};
+#else
+S20 s20;
+// expected-error at second.h:* {{'FunctionTemplate::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S21 {
+  template <template<class> class...> void foo();
+  template <template<class> class> void foo();
+};
+#elif defined(SECOND)
+struct S21 {
+  template <template<class> class> void foo();
+  template <template<class> class...> void foo();
+};
+#else
+S21 s21;
+// expected-error at second.h:* {{'FunctionTemplate::S21' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S22 {
+  template <template<class> class> void foo();
+  template <class> void foo();
+  template <int> void foo();
+};
+#elif defined(SECOND)
+struct S22 {
+  template <class> void foo();
+  template <int> void foo();
+  template <template<class> class> void foo();
+};
+#else
+S22 s22;
+// expected-error at second.h:* {{'FunctionTemplate::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a type template parameter}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a template template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S23 {
+  template <class> void foo();
+  template <int> void foo();
+  template <template<class> class> void foo();
+};
+#elif defined(SECOND)
+struct S23 {
+  template <int> void foo();
+  template <template<class> class> void foo();
+  template <class> void foo();
+};
+#else
+S23 s23;
+// expected-error at second.h:* {{'FunctionTemplate::S23' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a non-type template parameter}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a type template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S24 {
+  template <int> void foo();
+  template <template<class> class> void foo();
+  template <class> void foo();
+};
+#elif defined(SECOND)
+struct S24 {
+  template <template<class> class> void foo();
+  template <class> void foo();
+  template <int> void foo();
+};
+#else
+S24 s24;
+// expected-error at second.h:* {{'FunctionTemplate::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template template parameter}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a non-type template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S25 {
+  template <int> void foo();
+};
+#elif defined(SECOND)
+struct S25 {
+ public:
+  template <int> void foo();
+};
+#else
+S25 s25;
+// expected-error at second.h:* {{'FunctionTemplate::S25' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note at first.h:* {{but in 'FirstModule' found function template}}
+#endif
+
+#define DECLS                                           \
+  template <int>                                        \
+  void nontype1();                                      \
+  template <int x>                                      \
+  void nontype2();                                      \
+  template <int, int>                                   \
+  void nontype3();                                      \
+  template <int x = 5>                                  \
+  void nontype4();                                      \
+  template <int... x>                                   \
+  void nontype5();                                      \
+                                                        \
+  template <class>                                      \
+  void type1();                                         \
+  template <class x>                                    \
+  void type2();                                         \
+  template <class, class>                               \
+  void type3();                                         \
+  template <class x = int>                              \
+  void type4();                                         \
+  template <class... x>                                 \
+  void type5();                                         \
+                                                        \
+  template <template <int> class>                       \
+  void template1();                                     \
+  template <template <int> class x>                     \
+  void template2();                                     \
+  template <template <int> class, template <int> class> \
+  void template3();                                     \
+  template <template <int> class x = U>                 \
+  void template4();                                     \
+  template <template <int> class... x>                  \
+  void template5();
+
+#if defined(FIRST) || defined(SECOND)
+template<int>
+struct U {};
+struct Valid1 {
+  DECLS
+};
+#else
+Valid1 v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+  DECLS
+  ACCESS
+};
+#else
+Invalid1 i1;
+// expected-error at second.h:* {{'FunctionTemplate::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note at first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+#undef DECLS
+}
 
 // Collection of interesting cases below.
 




More information about the cfe-commits mailing list