]> granicus.if.org Git - clang/commitdiff
[ODRHash] Add diagnostic messages for typedef and type alias.
authorRichard Trieu <rtrieu@google.com>
Mon, 12 Jun 2017 21:58:22 +0000 (21:58 +0000)
committerRichard Trieu <rtrieu@google.com>
Mon, 12 Jun 2017 21:58:22 +0000 (21:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305238 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSerializationKinds.td
lib/Serialization/ASTReader.cpp
test/Modules/odr_hash.cpp

index 7c9e8c8980aa0e58efff1c2bb53cdcd9b1976443..5d286ee83a31c06f43d394921abc76020606b91a 100644 (file)
@@ -121,10 +121,10 @@ def err_module_odr_violation_mismatch_decl : Error<
   "%q0 has different definitions in different modules; first difference is "
   "%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}3">;
+  "protected access specifier|static assert|field|method|type alias|typedef}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}1">;
+  "protected access specifier|static assert|field|method|type alias|typedef}1">;
 
 def err_module_odr_violation_mismatch_decl_diff : Error<
   "%q0 has different definitions in different modules; first difference is "
@@ -149,7 +149,9 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
   "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}3">;
+  "method %4 with %ordinal5 parameter named %6|"
+  "%select{typedef|type alias}4 name %5|"
+  "%select{typedef|type alias}4 %5 with underlying type %6}3">;
 
 def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
   "%select{"
@@ -172,15 +174,19 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
   "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}1">;
+  "method %2 with %ordinal3 parameter named %4|"
+  "%select{typedef|type alias}2 name %3|"
+  "%select{typedef|type alias}2 %3 with different underlying type %4}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 "
-  "%select{||||static assert|field|method|unexpected decl}3">;
+  "%select{||||static assert|field|method|type alias|typedef|"
+  "unexpected decl}3">;
 def note_module_odr_violation_mismatch_decl_unknown : Note<
   "but in '%0' found "
   "%select{||||different static assert|different field|different method|"
+  "different type alias|different typedef|"
   "another unexpected decl}1">;
 
 def warn_duplicate_module_file_extension : Warning<
index 94a8f609f57c0000257d9bdb77ac911f2828ce78..5bef65fc8900bc0d9fa5e318d63da448eba5aa07 100644 (file)
@@ -9242,6 +9242,7 @@ void ASTReader::diagnoseOdrViolations() {
 
       // Used with err_module_odr_violation_mismatch_decl and
       // note_module_odr_violation_mismatch_decl
+      // This list should be the same Decl's as in ODRHash::isWhiteListedDecl
       enum {
         EndOfClass,
         PublicSpecifer,
@@ -9250,6 +9251,8 @@ void ASTReader::diagnoseOdrViolations() {
         StaticAssert,
         Field,
         CXXMethod,
+        TypeAlias,
+        TypeDef,
         Other
       } FirstDiffType = Other,
         SecondDiffType = Other;
@@ -9277,6 +9280,10 @@ void ASTReader::diagnoseOdrViolations() {
           return Field;
         case Decl::CXXMethod:
           return CXXMethod;
+        case Decl::TypeAlias:
+          return TypeAlias;
+        case Decl::Typedef:
+          return TypeDef;
         }
       };
 
@@ -9373,6 +9380,8 @@ void ASTReader::diagnoseOdrViolations() {
         MethodNumberParameters,
         MethodParameterType,
         MethodParameterName,
+        TypedefName,
+        TypedefType,
       };
 
       // These lambdas have the common portions of the ODR diagnostics.  This
@@ -9748,6 +9757,38 @@ void ASTReader::diagnoseOdrViolations() {
 
         break;
       }
+      case TypeAlias:
+      case TypeDef: {
+        TypedefNameDecl *FirstTD = cast<TypedefNameDecl>(FirstDecl);
+        TypedefNameDecl *SecondTD = cast<TypedefNameDecl>(SecondDecl);
+        auto FirstName = FirstTD->getDeclName();
+        auto SecondName = SecondTD->getDeclName();
+        if (FirstName != SecondName) {
+          ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
+                       TypedefName)
+              << (FirstDiffType == TypeAlias) << FirstName;
+          ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
+                      TypedefName)
+              << (FirstDiffType == TypeAlias) << SecondName;
+          Diagnosed = true;
+          break;
+        }
+
+        QualType FirstType = FirstTD->getUnderlyingType();
+        QualType SecondType = SecondTD->getUnderlyingType();
+        if (ComputeQualTypeODRHash(FirstType) !=
+            ComputeQualTypeODRHash(SecondType)) {
+          ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
+                       TypedefType)
+              << (FirstDiffType == TypeAlias) << FirstName << FirstType;
+          ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
+                      TypedefType)
+              << (FirstDiffType == TypeAlias) << SecondName << SecondType;
+          Diagnosed = true;
+          break;
+        }
+        break;
+      }
       }
 
       if (Diagnosed == true)
index a6a0b74743aaa315fa03c8cc8df3502abb7e3dac..cc953d0c05466c5b799bb300ff4c89206164ea00 100644 (file)
@@ -586,6 +586,57 @@ S3 s3;
 // expected-error@first.h:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}}
 // expected-note@second.h:* {{declaration of 'a' does not match}}
 #endif
+
+#if defined(FIRST)
+struct S4 {
+  typedef int a;
+  typedef int b;
+};
+#elif defined(SECOND)
+struct S4 {
+  typedef int b;
+  typedef int a;
+};
+#else
+S4 s4;
+// expected-error@second.h:* {{'TypeDef::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef name 'b'}}
+// expected-note@first.h:* {{but in 'FirstModule' found typedef name 'a'}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+  typedef int a;
+  typedef int b;
+  int x;
+};
+#elif defined(SECOND)
+struct S5 {
+  int x;
+  typedef int b;
+  typedef int a;
+};
+#else
+S5 s5;
+// expected-error@second.h:* {{'TypeDef::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
+// expected-note@first.h:* {{but in 'FirstModule' found typedef}}
+#endif
+
+#if defined(FIRST)
+typedef float F;
+struct S6 {
+  typedef int a;
+  typedef F b;
+};
+#elif defined(SECOND)
+struct S6 {
+  typedef int a;
+  typedef float b;
+};
+#else
+S6 s6;
+// expected-error@second.h:* {{'TypeDef::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef 'b' with underlying type 'float'}}
+// expected-note@first.h:* {{but in 'FirstModule' found typedef 'b' with different underlying type 'TypeDef::F' (aka 'float')}}
+#endif
 }  // namespace TypeDef
 
 namespace Using {
@@ -632,6 +683,57 @@ S3 s3;
 // expected-error@first.h:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}}
 // expected-note@second.h:* {{declaration of 'a' does not match}}
 #endif
+
+#if defined(FIRST)
+struct S4 {
+  using a = int;
+  using b = int;
+};
+#elif defined(SECOND)
+struct S4 {
+  using b = int;
+  using a = int;
+};
+#else
+S4 s4;
+// expected-error@second.h:* {{'Using::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias name 'b'}}
+// expected-note@first.h:* {{but in 'FirstModule' found type alias name 'a'}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+  using a = int;
+  using b = int;
+  int x;
+};
+#elif defined(SECOND)
+struct S5 {
+  int x;
+  using b = int;
+  using a = int;
+};
+#else
+S5 s5;
+// expected-error@second.h:* {{'Using::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
+// expected-note@first.h:* {{but in 'FirstModule' found type alias}}
+#endif
+
+#if defined(FIRST)
+typedef float F;
+struct S6 {
+  using a = int;
+  using b = F;
+};
+#elif defined(SECOND)
+struct S6 {
+  using a = int;
+  using b = float;
+};
+#else
+S6 s6;
+// expected-error@second.h:* {{'Using::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'b' with underlying type 'float'}}
+// expected-note@first.h:* {{but in 'FirstModule' found type alias 'b' with different underlying type 'Using::F' (aka 'float')}}
+#endif
 }  // namespace Using
 
 namespace RecordType {