r296078 - [ODRHash] Add handling of TypedefType and DeclarationName

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 23 18:59:12 PST 2017


Author: rtrieu
Date: Thu Feb 23 20:59:12 2017
New Revision: 296078

URL: http://llvm.org/viewvc/llvm-project?rev=296078&view=rev
Log:
[ODRHash] Add handling of TypedefType and DeclarationName

Differential Revision: https://reviews.llvm.org/D21675

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=296078&r1=296077&r2=296078&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Thu Feb 23 20:59:12 2017
@@ -133,14 +133,14 @@ def err_module_odr_violation_mismatch_de
   "static assert with condition|"
   "static assert with message|"
   "static assert with %select{|no }4message|"
-  "field %4}3">;
+  "field %4|field %4 with type %5}3">;
 
 def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
   "%select{"
   "static assert with different condition|"
   "static assert with different message|"
   "static assert with %select{|no }2message|"
-  "field %2}1">;
+  "field %2|field %2 with type %3}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=296078&r1=296077&r2=296078&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ODRHash.cpp (original)
+++ cfe/trunk/lib/AST/ODRHash.cpp Thu Feb 23 20:59:12 2017
@@ -32,9 +32,57 @@ void ODRHash::AddIdentifierInfo(const Id
   ID.AddString(II->getName());
 }
 
+void ODRHash::AddDeclarationName(DeclarationName Name) {
+  AddBoolean(Name.isEmpty());
+  if (Name.isEmpty())
+    return;
+
+  auto Kind = Name.getNameKind();
+  ID.AddInteger(Kind);
+  switch (Kind) {
+  case DeclarationName::Identifier:
+    AddIdentifierInfo(Name.getAsIdentifierInfo());
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector: {
+    Selector S = Name.getObjCSelector();
+    AddBoolean(S.isNull());
+    AddBoolean(S.isKeywordSelector());
+    AddBoolean(S.isUnarySelector());
+    unsigned NumArgs = S.getNumArgs();
+    for (unsigned i = 0; i < NumArgs; ++i) {
+      AddIdentifierInfo(S.getIdentifierInfoForSlot(i));
+    }
+    break;
+  }
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+    AddQualType(Name.getCXXNameType());
+    break;
+  case DeclarationName::CXXOperatorName:
+    ID.AddInteger(Name.getCXXOverloadedOperator());
+    break;
+  case DeclarationName::CXXLiteralOperatorName:
+    AddIdentifierInfo(Name.getCXXLiteralIdentifier());
+    break;
+  case DeclarationName::CXXConversionFunctionName:
+    AddQualType(Name.getCXXNameType());
+    break;
+  case DeclarationName::CXXUsingDirective:
+    break;
+  case DeclarationName::CXXDeductionGuideName: {
+    auto *Template = Name.getCXXDeductionGuideTemplate();
+    AddBoolean(Template);
+    if (Template) {
+      AddDecl(Template);
+    }
+  }
+  }
+}
+
 void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {}
 void ODRHash::AddTemplateName(TemplateName Name) {}
-void ODRHash::AddDeclarationName(DeclarationName Name) {}
 void ODRHash::AddTemplateArgument(TemplateArgument TA) {}
 void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
 
@@ -192,6 +240,10 @@ void ODRHash::AddDecl(const Decl *D) {
   }
 
   ID.AddInteger(D->getKind());
+
+  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+    AddDeclarationName(ND->getDeclName());
+  }
 }
 
 // Process a Type pointer.  Add* methods call back into ODRHash while Visit*
@@ -212,6 +264,13 @@ public:
     }
   }
 
+  void AddDecl(Decl *D) {
+    Hash.AddBoolean(D);
+    if (D) {
+      Hash.AddDecl(D);
+    }
+  }
+
   void Visit(const Type *T) {
     ID.AddInteger(T->getTypeClass());
     Inherited::Visit(T);
@@ -223,6 +282,11 @@ public:
     ID.AddInteger(T->getKind());
     VisitType(T);
   }
+
+  void VisitTypedefType(const TypedefType *T) {
+    AddDecl(T->getDecl());
+    VisitType(T);
+  }
 };
 
 void ODRHash::AddType(const Type *T) {

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=296078&r1=296077&r2=296078&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Feb 23 20:59:12 2017
@@ -9062,6 +9062,7 @@ void ASTReader::diagnoseOdrViolations()
         StaticAssertMessage,
         StaticAssertOnlyMessage,
         FieldName,
+        FieldTypeName,
       };
 
       // These lambdas have the common portions of the ODR diagnostics.  This
@@ -9086,6 +9087,12 @@ void ASTReader::diagnoseOdrViolations()
         return Hash.CalculateHash();
       };
 
+      auto ComputeDeclNameODRHash = [&Hash](const DeclarationName Name) {
+        Hash.clear();
+        Hash.AddDeclarationName(Name);
+        return Hash.CalculateHash();
+      };
+
       switch (FirstDiffType) {
       case Other:
       case EndOfClass:
@@ -9166,6 +9173,46 @@ void ASTReader::diagnoseOdrViolations()
           Diagnosed = true;
           break;
         }
+
+        assert(
+            Context.hasSameType(FirstField->getType(), SecondField->getType()));
+
+        QualType FirstType = FirstField->getType();
+        QualType SecondType = SecondField->getType();
+        const TypedefType *FirstTypedef = dyn_cast<TypedefType>(FirstType);
+        const TypedefType *SecondTypedef = dyn_cast<TypedefType>(SecondType);
+
+        if ((FirstTypedef && !SecondTypedef) ||
+            (!FirstTypedef && SecondTypedef)) {
+          ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
+                       FieldTypeName)
+              << FirstII << FirstType;
+          ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
+                      FieldTypeName)
+              << SecondII << SecondType;
+
+          Diagnosed = true;
+          break;
+        }
+
+        if (FirstTypedef && SecondTypedef) {
+          unsigned FirstHash = ComputeDeclNameODRHash(
+              FirstTypedef->getDecl()->getDeclName());
+          unsigned SecondHash = ComputeDeclNameODRHash(
+              SecondTypedef->getDecl()->getDeclName());
+          if (FirstHash != SecondHash) {
+            ODRDiagError(FirstField->getLocation(),
+                         FirstField->getSourceRange(), FieldTypeName)
+                << FirstII << FirstType;
+            ODRDiagNote(SecondField->getLocation(),
+                        SecondField->getSourceRange(), FieldTypeName)
+                << SecondII << SecondType;
+
+            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=296078&r1=296077&r2=296078&view=diff
==============================================================================
--- cfe/trunk/test/Modules/odr_hash.cpp (original)
+++ cfe/trunk/test/Modules/odr_hash.cpp Thu Feb 23 20:59:12 2017
@@ -162,6 +162,36 @@ S3 s3;
 // expected-error at first.h:* {{'Field::S3::x' from module 'FirstModule' is not present in definition of 'Field::S3' in module 'SecondModule'}}
 // expected-note at second.h:* {{declaration of 'x' does not match}}
 #endif
+
+#if defined(FIRST)
+typedef int A;
+struct S4 {
+  A x;
+};
+
+struct S5 {
+  A x;
+};
+#elif defined(SECOND)
+typedef int B;
+struct S4 {
+  B x;
+};
+
+struct S5 {
+  int x;
+};
+#else
+S4 s4;
+// expected-error at second.h:* {{'Field::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'B' (aka 'int')}}
+// expected-note at first.h:* {{but in 'FirstModule' found field 'x' with type 'A' (aka 'int')}}
+
+S5 s5;
+// expected-error at second.h:* {{'Field::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'int'}}
+// expected-note at first.h:* {{but in 'FirstModule' found field 'x' with type 'A' (aka 'int')}}
+#endif
+
+
 }  // namespace Field
 
 // Naive parsing of AST can lead to cycles in processing.  Ensure
@@ -193,6 +223,7 @@ struct NestedNamespaceSpecifier {};
 // while struct T should error at the access specifier mismatch at the end.
 namespace AllDecls {
 #if defined(FIRST)
+typedef int INT;
 struct S {
   public:
   private:
@@ -203,8 +234,11 @@ struct S {
 
   int x;
   double y;
+
+  INT z;
 };
 #elif defined(SECOND)
+typedef int INT;
 struct S {
   public:
   private:
@@ -215,12 +249,15 @@ struct S {
 
   int x;
   double y;
+
+  INT z;
 };
 #else
 S s;
 #endif
 
 #if defined(FIRST)
+typedef int INT;
 struct T {
   public:
   private:
@@ -232,9 +269,12 @@ struct T {
   int x;
   double y;
 
+  INT z;
+
   private:
 };
 #elif defined(SECOND)
+typedef int INT;
 struct T {
   public:
   private:
@@ -246,6 +286,8 @@ struct T {
   int x;
   double y;
 
+  INT z;
+
   public:
 };
 #else




More information about the cfe-commits mailing list