nomanous updated this revision to Diff 301872.
nomanous added a comment.

Change some format.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D90448/new/

https://reviews.llvm.org/D90448

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/SemaCXX/template-explicit-instant-type-mismatch.cpp

Index: clang/test/SemaCXX/template-explicit-instant-type-mismatch.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/template-explicit-instant-type-mismatch.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+template<typename T>
+class A
+{
+ static T a; //expected-note {{in instantiation of static data member 'A<B>::a' requested here}}
+};
+
+template<typename T>
+T A<T>::a;
+
+class B
+{ };
+
+template<typename T> T c; //expected-note {{variable template 'c' declared here}}
+
+template int c<B>; //expected-error {{type 'int' of explicit instantiation of 'c' does not match expected type 'B'}}
+
+template int A<B>::a; //expected-error {{type 'int' of explicit instantiation of 'A<B>::a' does not match expected type 'B'}}
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -9977,6 +9977,7 @@
 
     VarDecl *Prev = Previous.getAsSingle<VarDecl>();
     VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>();
+    bool IsStaticDataMemberInstantiation = false;
 
     if (!PrevTemplate) {
       if (!Prev || !Prev->isStaticDataMember()) {
@@ -9998,6 +9999,8 @@
         // FIXME: Can we provide a note showing where this was declared?
         return true;
       }
+
+      IsStaticDataMemberInstantiation = true;
     } else {
       // Explicitly instantiate a variable template.
 
@@ -10090,6 +10093,23 @@
       return true;
     }
 
+    // Check the static member's type given in the explicit instantiation
+    // definition against the one in the class template. This won't happen in
+    // explicit instantiation declaration because the instantiated code won't
+    // be generated in that case. Objective C lifetime qualifiers will be
+    // automatically added by compiler with option -fobjc-arc so it should be
+    // ignored when comparing types.
+    if (IsStaticDataMemberInstantiation &&
+        TSK==TSK_ExplicitInstantiationDefinition && Prev &&
+        !Context.hasSameType(Prev->getType(), R, true)) {
+      Diag(T->getTypeLoc().getBeginLoc(),
+           diag::err_invalid_template_static_data_member_spec_type)
+          << Prev << R << Prev->getType();
+      Diag(Prev->getLocation(), diag::note_template_static_data_member_def_here)
+          <<Prev;
+      return true;
+    }
+
     // FIXME: Create an ExplicitInstantiation node?
     return (Decl*) nullptr;
   }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5034,6 +5034,8 @@
   "of %select{explicit instantiation|explicit specialization|"
   "partial specialization|redeclaration}0 of %1 does not match"
   " expected type %3">;
+def err_invalid_template_static_data_member_spec_type : Error<"type %1 "
+  "of explicit instantiation of %q0 does not match expected type %2">;
 def err_mismatched_exception_spec_explicit_instantiation : Error<
   "exception specification in explicit instantiation does not match "
   "instantiated one">;
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -2337,8 +2337,19 @@
   CanQualType getCanonicalParamType(QualType T) const;
 
   /// Determine whether the given types \p T1 and \p T2 are equivalent.
-  bool hasSameType(QualType T1, QualType T2) const {
-    return getCanonicalType(T1) == getCanonicalType(T2);
+  /// The lifetime qualifier of Objective C can be chosen to be ignored because
+  /// sometimes we don't want to take this into consideration.
+  bool hasSameType(QualType T1, QualType T2,
+                   bool IgnoreObjCLifetimeQual = false) const {
+    if (!IgnoreObjCLifetimeQual) {
+      return getCanonicalType(T1) == getCanonicalType(T2);
+    } else {
+      SplitQualType ST1 = getCanonicalType(T1).split();
+      SplitQualType ST2 = getCanonicalType(T2).split();
+      ST1.Quals.removeObjCLifetime();
+      ST2.Quals.removeObjCLifetime();
+      return ST1 == ST2;
+    }
   }
   bool hasSameType(const Type *T1, const Type *T2) const {
     return getCanonicalType(T1) == getCanonicalType(T2);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to