]> granicus.if.org Git - clang/commitdiff
[ODRHash] Add basic support for CXXRecordDecl
authorRichard Trieu <rtrieu@google.com>
Tue, 28 Feb 2017 21:24:38 +0000 (21:24 +0000)
committerRichard Trieu <rtrieu@google.com>
Tue, 28 Feb 2017 21:24:38 +0000 (21:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296521 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 78efc69f577afe5aaadae3e18862f49ef8bbc9f1..4d6ffa1b2a85b4f9baa40ecdd0f81cc788be207a 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}3">;
+  "protected access specifier|static assert|field|method}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}1">;
+  "protected access specifier|static assert|field|method}1">;
 
 def err_module_odr_violation_mismatch_decl_diff : Error<
   "%q0 has different definitions in different modules; first difference is "
@@ -139,7 +139,8 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
   "bitfield %4 with one width expression|"
   "%select{non-|}5mutable field %4|"
   "field %4 with %select{no|an}5 initalizer|"
-  "field %4 with an initializer}3">;
+  "field %4 with an initializer|"
+  "method %4}3">;
 
 def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
   "%select{"
@@ -152,7 +153,8 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
   "bitfield %2 with different width expression|"
   "%select{non-|}3mutable field %2|"
   "field %2 with %select{no|an}3 initializer|"
-  "field %2 with a different initializer}1">;
+  "field %2 with a different initializer|"
+  "method %2}1">;
 
 def warn_module_uses_date_time : Warning<
   "%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
index d8c2e20ede671318f158c0adfb177d0a81b882ad..78a3eeca034dfa11c12a9cdc37726796577b1be6 100644 (file)
@@ -194,6 +194,14 @@ public:
 
     Inherited::VisitFieldDecl(D);
   }
+
+  void VisitFunctionDecl(const FunctionDecl *D) {
+    Inherited::VisitFunctionDecl(D);
+  }
+
+  void VisitCXXMethodDecl(const CXXMethodDecl *D) {
+    Inherited::VisitCXXMethodDecl(D);
+  }
 };
 
 // Only allow a small portion of Decl's to be processed.  Remove this once
@@ -206,6 +214,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
     default:
       return false;
     case Decl::AccessSpec:
+    case Decl::CXXMethod:
     case Decl::Field:
     case Decl::StaticAssert:
       return true;
index 982f59272e9a43a3946fae231b4515b6ea4b5220..e9cb51dec6ed69f0d5907b993f6f6fd0c1c174b2 100644 (file)
@@ -8957,6 +8957,7 @@ void ASTReader::diagnoseOdrViolations() {
         ProtectedSpecifer,
         StaticAssert,
         Field,
+        CXXMethod,
         Other
       } FirstDiffType = Other,
         SecondDiffType = Other;
@@ -8982,6 +8983,8 @@ void ASTReader::diagnoseOdrViolations() {
           return StaticAssert;
         case Decl::Field:
           return Field;
+        case Decl::CXXMethod:
+          return CXXMethod;
         }
       };
 
@@ -9068,6 +9071,7 @@ void ASTReader::diagnoseOdrViolations() {
         FieldSingleMutable,
         FieldSingleInitializer,
         FieldDifferentInitializers,
+        MethodName,
       };
 
       // These lambdas have the common portions of the ODR diagnostics.  This
@@ -9288,6 +9292,25 @@ void ASTReader::diagnoseOdrViolations() {
 
         break;
       }
+      case CXXMethod: {
+        const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl);
+        const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl);
+        IdentifierInfo *FirstII = FirstMethod->getIdentifier();
+        IdentifierInfo *SecondII = SecondMethod->getIdentifier();
+        if (FirstII->getName() != SecondII->getName()) {
+          ODRDiagError(FirstMethod->getLocation(),
+                       FirstMethod->getSourceRange(), MethodName)
+              << FirstII;
+          ODRDiagNote(SecondMethod->getLocation(),
+                      SecondMethod->getSourceRange(), MethodName)
+              << SecondII;
+
+          Diagnosed = true;
+          break;
+        }
+
+        break;
+      }
       }
 
       if (Diagnosed == true)
index e485f633f89dfc97efa864674f070b4d60655b05..c1ea3b034ff8a63ed6053e88a7defb077c6ff899 100644 (file)
@@ -277,6 +277,39 @@ S11 s11;
 
 }  // namespace Field
 
+namespace Method {
+#if defined(FIRST)
+struct S1 {
+  void A() {}
+};
+#elif defined(SECOND)
+struct S1 {
+  private:
+  void A() {}
+};
+#else
+S1 s1;
+// expected-error@second.h:* {{'Method::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found method}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+  void A() {}
+  void B() {}
+};
+#elif defined(SECOND)
+struct S2 {
+  void B() {}
+  void A() {}
+};
+#else
+S2 s2;
+// expected-error@second.h:* {{'Method::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'B'}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A'}}
+#endif
+}  // namespace Method
+
 // Naive parsing of AST can lead to cycles in processing.  Ensure
 // self-references don't trigger an endless cycles of AST node processing.
 namespace SelfReference {
@@ -324,6 +357,8 @@ struct S {
   unsigned b : 2*2 + 5/2;
 
   mutable int c = sizeof(x + y);
+
+  void method() {}
 };
 #elif defined(SECOND)
 typedef int INT;
@@ -344,6 +379,8 @@ struct S {
   unsigned b : 2 * 2 + 5 / 2;
 
   mutable int c = sizeof(x + y);
+
+  void method() {}
 };
 #else
 S s;
@@ -369,6 +406,8 @@ struct T {
 
   mutable int c = sizeof(x + y);
 
+  void method() {}
+
   private:
 };
 #elif defined(SECOND)
@@ -391,6 +430,8 @@ struct T {
 
   mutable int c = sizeof(x + y);
 
+  void method() {}
+
   public:
 };
 #else