]> granicus.if.org Git - clang/commitdiff
Ensure code generation for friend declarations in class templates.
authorJohn McCall <rjmccall@apple.com>
Sat, 29 Aug 2009 03:16:09 +0000 (03:16 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 29 Aug 2009 03:16:09 +0000 (03:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80418 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CXX/temp/temp.decls/temp.friend/p1.cpp

index 4cb5a276e64fa5a07d30bda11543b404ebf8448b..521394b978af61b080bc9814500587c5056e0692 100644 (file)
@@ -37,7 +37,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
   if (!Ctx)
     Ctx = D->getDeclContext();
   
-  for (; !Ctx->isFileContext(); Ctx = Ctx->getParent()) {
+  while (!Ctx->isFileContext()) {
     // Add template arguments from a class template instantiation.
     if (ClassTemplateSpecializationDecl *Spec 
           = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
@@ -46,18 +46,26 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
         break;
       
       Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
-      continue;
     } 
     
     // Add template arguments from a function template specialization.
-    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
+    else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
       // FIXME: Check whether this is an explicit specialization.
       if (const TemplateArgumentList *TemplateArgs
             = Function->getTemplateSpecializationArgs())
         Result.addOuterTemplateArguments(TemplateArgs);
-      
-      continue;
+
+      // If this is a friend declaration and it declares an entity at
+      // namespace scope, take arguments from its lexical parent
+      // instead of its semantic parent.
+      if (Function->getFriendObjectKind() &&
+          Function->getDeclContext()->isFileContext()) {
+        Ctx = Function->getLexicalDeclContext();
+        continue;
+      }
     }
+
+    Ctx = Ctx->getParent();
   }
   
   return Result;
index 8370bd17efad77d7fd83ffc0480329955ce1f882..df4ebfaa93352a73564b738b42964d8e81ca8c9a 100644 (file)
@@ -498,6 +498,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
     Function->setObjectOfFriendDecl(WasDeclared);
     if (!Owner->isDependentContext())
       DC->makeDeclVisibleInContext(Function);
+
+    Function->setInstantiationOfMemberFunction(D);
   }
   
   if (InitFunctionInstantiation(Function, D))
index b834257889eff8a7d07bbd670d8d60a7586ee235..fe92f4d759e2ff6f1efa829435c498cc03d3301f 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc %s
 
 template <typename T> struct Num {
   T value_;
@@ -38,7 +38,7 @@ int calc1() {
 
 int calc2() {
   Num<int> x = 3;
-  Num<int>::Rep<char> n = 10;
+  Num<int>::Rep<char> n = (cast) 10;
   Num<int> result = x * n;
   return result.get();
 }