]> granicus.if.org Git - clang/commitdiff
When we encounter a non-dependent type during template instantiation,
authorDouglas Gregor <dgregor@apple.com>
Fri, 7 May 2010 23:12:07 +0000 (23:12 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 7 May 2010 23:12:07 +0000 (23:12 +0000)
mark any declarations we see inside of that type as
"referenced". Fixes PR7079.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103323 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/RecursiveASTVisitor.h
lib/Frontend/BoostConAction.cpp
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-non-dependent-types.cpp [new file with mode: 0644]

index a3d639e94b40e5786f6fd02f393ef3eefe997eb3..27823694c759913c38201e11ca3e4160ff687084 100644 (file)
@@ -257,6 +257,8 @@ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S);
    case Type::Class: DISPATCH(Class##Type, Class##Type, T.getTypePtr());
 #include "clang/AST/TypeNodes.def"
     }
+    
+    return false;
   }
   
   template<typename Derived>
@@ -291,6 +293,8 @@ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S);
     case NestedNameSpecifier::TypeSpecWithTemplate:
       return Visit(QualType(NNS->getAsType(), 0));
     }
+    
+    return false;
   }
 
   template<typename Derived>
@@ -327,6 +331,8 @@ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S);
       return getDerived().VisitTemplateArguments(Arg.pack_begin(), 
                                                  Arg.pack_size());
     }
+    
+    return false;
   }
   
   template<typename Derived>
@@ -614,7 +620,8 @@ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S);
       return true;
     
     if (T->getTemplateId() &&
-        getDerived().VisitTemplateSpecializationType(T->getTemplateId()))
+        getDerived().VisitTemplateSpecializationType(
+                  const_cast<TemplateSpecializationType *>(T->getTemplateId())))
       return true;
     
     return getDerived().VisitType(T);
index 6995969fdf9709a74723d1a3f0c739a5f49079d1..ae150c6ec21e30569cc944a1d43ef6fbfb62e673 100644 (file)
@@ -10,6 +10,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include <cstdio>
+#include <iostream>
 using namespace clang;
 
 namespace {
@@ -19,6 +20,11 @@ namespace {
     /// HandleTranslationUnit - This method is called when the ASTs for entire
     /// translation unit have been parsed.
     virtual void HandleTranslationUnit(ASTContext &Ctx);
+                                
+    bool VisitCXXRecordDecl(CXXRecordDecl *D) {
+      std::cout << D->getNameAsString() << std::endl;
+      return false;
+    }                                
   };
 }
 
index 1bc2a72179f2caca85ec442e2abfe8cc02a0d7a0..24480fe81a08036fcdf6adac4d058611dbe8afdf 100644 (file)
@@ -1784,6 +1784,7 @@ public:
   virtual void PopExpressionEvaluationContext();
 
   void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+  void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
   bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
 
   // Primary Expressions.
index 03964587e9e80341e13e88b53777e8ad87a00915..73493b60662b15698de8bc5ab1ad684c0293a536 100644 (file)
@@ -22,6 +22,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
@@ -7572,6 +7573,48 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
   }
 }
 
+namespace {
+  // Mark all of the declarations referenced 
+  // FIXME: Not fully implemented yet! We need to have a better understanding
+  // of when we're entering 
+  class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
+    Sema &S;
+    SourceLocation Loc;
+    
+  public:
+    typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
+    
+    MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
+    
+    bool VisitTemplateArgument(const TemplateArgument &Arg);
+    bool VisitRecordType(RecordType *T);
+  };
+}
+
+bool MarkReferencedDecls::VisitTemplateArgument(const TemplateArgument &Arg) {
+  if (Arg.getKind() == TemplateArgument::Declaration) {
+    S.MarkDeclarationReferenced(Loc, Arg.getAsDecl());
+  }
+  
+  return Inherited::VisitTemplateArgument(Arg);
+}
+
+bool MarkReferencedDecls::VisitRecordType(RecordType *T) {
+  if (ClassTemplateSpecializationDecl *Spec
+                  = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
+    const TemplateArgumentList &Args = Spec->getTemplateArgs();
+    return VisitTemplateArguments(Args.getFlatArgumentList(), 
+                                  Args.flat_size());
+  }
+
+  return false;
+}
+
+void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
+  MarkReferencedDecls Marker(*this, Loc);
+  Marker.Visit(Context.getCanonicalType(T));
+}
+
 /// \brief Emit a diagnostic that describes an effect on the run-time behavior
 /// of the program being compiled.
 ///
index c7489ad821076f78db09a350767cf3cd88d7681a..7dab4bd8bd55b67f358d9bfef8a0a9bf5d17af28 100644 (file)
@@ -560,9 +560,7 @@ namespace {
     ///
     /// For the purposes of template instantiation, a type has already been
     /// transformed if it is NULL or if it is not dependent.
-    bool AlreadyTransformed(QualType T) {
-      return T.isNull() || !T->isDependentType();
-    }
+    bool AlreadyTransformed(QualType T);
 
     /// \brief Returns the location of the entity being instantiated, if known.
     SourceLocation getBaseLocation() { return Loc; }
@@ -624,6 +622,17 @@ namespace {
   };
 }
 
+bool TemplateInstantiator::AlreadyTransformed(QualType T) {
+  if (T.isNull())
+    return true;
+  
+  if (T->isDependentType())
+    return false;
+  
+  getSema().MarkDeclarationsReferencedInType(Loc, T);
+  return true;
+}
+
 Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
   if (!D)
     return 0;
index 44bce7976c8e35d70103878a930dfaf5e517e09d..a32c0e1ac32af3eaa658cddd8cf0a1cff6ef9e78 100644 (file)
@@ -191,6 +191,8 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
       Invalid = true;
       DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy);
     }
+  } else {
+    SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
   }
 
   // Create the new typedef
@@ -440,6 +442,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
         << DI->getType();
       Invalid = true;
     }
+  } else {
+    SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
   }
 
   Expr *BitWidth = D->getBitWidth();
diff --git a/test/SemaTemplate/instantiate-non-dependent-types.cpp b/test/SemaTemplate/instantiate-non-dependent-types.cpp
new file mode 100644 (file)
index 0000000..a0005c5
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+template<typename T>
+struct X1 {
+  static void member() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+};
+
+template<void(*)()> struct instantiate { };
+
+template<typename T>
+struct X2 {
+  typedef instantiate<&X1<int>::member> i; // expected-note{{in instantiation of}}
+};
+
+X2<int> x;