[cfe-commits] r116373 - in /cfe/trunk: include/clang/Basic/Diagnostic.h include/clang/Basic/PartialDiagnostic.h include/clang/Sema/Sema.h include/clang/Sema/TemplateDeduction.h lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiate.cpp test/CXX/temp/temp.arg/temp.arg.type/p2.cpp

Douglas Gregor dgregor at apple.com
Tue Oct 12 16:32:35 PDT 2010


Author: dgregor
Date: Tue Oct 12 18:32:35 2010
New Revision: 116373

URL: http://llvm.org/viewvc/llvm-project?rev=116373&view=rev
Log:
Introduce support for emitting diagnostics (warnings + their notes)
that are suppressed during template argument deduction. This change
queues diagnostics computed during template argument deduction. Then,
if the resulting function template specialization or partial
specialization is chosen by overload resolution or partial ordering
(respectively), we will emit the queued diagnostics at that point. 

This addresses most of PR6784. However, the check for unnamed/local
template arguments (which existed before this change) is still only
skin-deep, and needs to be extended to look deeper into types. It must
be improved to finish PR6784.


Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Basic/PartialDiagnostic.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/TemplateDeduction.h
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Tue Oct 12 18:32:35 2010
@@ -585,7 +585,8 @@
   // diagnostic is in flight at a time.
   friend class DiagnosticBuilder;
   friend class DiagnosticInfo;
-
+  friend class PartialDiagnostic;
+  
   /// CurDiagLoc - This is the location of the current diagnostic that is in
   /// flight.
   FullSourceLoc CurDiagLoc;
@@ -667,6 +668,8 @@
   explicit DiagnosticBuilder(Diagnostic *diagObj)
     : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
 
+  friend class PartialDiagnostic;
+  
 public:
   /// Copy constructor.  When copied, this "takes" the diagnostic info from the
   /// input and neuters it.
@@ -703,6 +706,17 @@
   /// isActive - Determine whether this diagnostic is still active.
   bool isActive() const { return DiagObj != 0; }
 
+  /// \brief Retrieve the active diagnostic ID.
+  ///
+  /// \pre \c isActive()
+  unsigned getDiagID() const {
+    assert(isActive() && "Diagnostic is inactive");
+    return DiagObj->CurDiagID;
+  }
+  
+  /// \brief Clear out the current diagnostic.
+  void Clear() { DiagObj = 0; }
+  
   /// Operator bool: conversion of DiagnosticBuilder to bool always returns
   /// true.  This allows is to be used in boolean error contexts like:
   /// return Diag(...);

Modified: cfe/trunk/include/clang/Basic/PartialDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/PartialDiagnostic.h?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/PartialDiagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/PartialDiagnostic.h Tue Oct 12 18:32:35 2010
@@ -57,6 +57,10 @@
     /// what sort of argument kind it is.
     intptr_t DiagArgumentsVal[MaxArguments];
   
+    /// \brief The values for the various substitution positions that have
+    /// string arguments.
+    std::string DiagArgumentsStr[MaxArguments];
+    
     /// DiagRanges - The list of ranges added to this diagnostic.  It currently
     /// only support 10 ranges, could easily be extended if needed.
     CharSourceRange DiagRanges[10];
@@ -186,6 +190,26 @@
       *this->DiagStorage = *Other.DiagStorage;
   }
   
+  PartialDiagnostic(const DiagnosticInfo &Other, StorageAllocator &Allocator)
+    : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator)
+  {
+    // Copy arguments.
+    for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
+      if (Other.getArgKind(I) == Diagnostic::ak_std_string)
+        AddString(Other.getArgStdStr(I));
+      else
+        AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
+    }
+    
+    // Copy source ranges.
+    for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
+      AddSourceRange(Other.getRange(I));
+    
+    // Copy fix-its.
+    for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
+      AddFixItHint(Other.getFixItHint(I));
+  }
+  
   PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
     DiagID = Other.DiagID;
     if (Other.DiagStorage) {
@@ -216,13 +240,28 @@
     DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
   }
 
+  void AddString(llvm::StringRef V) const {
+    if (!DiagStorage)
+      DiagStorage = getStorage();
+    
+    assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
+           "Too many arguments to diagnostic!");
+    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs]
+      = Diagnostic::ak_std_string;
+    DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = V;
+  }
+
   void Emit(const DiagnosticBuilder &DB) const {
     if (!DiagStorage)
       return;
     
     // Add all arguments.
     for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
-      DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
+      if ((Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
+            == Diagnostic::ak_std_string)
+        DB.AddString(DiagStorage->DiagArgumentsStr[i]);
+      else
+        DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
                    (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
     }
     
@@ -230,7 +269,7 @@
     for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
       DB.AddSourceRange(DiagStorage->DiagRanges[i]);
     
-    // Add all code modification hints
+    // Add all fix-its.
     for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i)
       DB.AddFixItHint(DiagStorage->FixItHints[i]);
   }
@@ -263,6 +302,13 @@
   }
 
   friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+                                                    llvm::StringRef S) {
+    
+    PD.AddString(S);
+    return PD;
+  }
+  
+  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                                     const SourceRange &R) {
     PD.AddSourceRange(CharSourceRange::getTokenRange(R));
     return PD;
@@ -288,6 +334,9 @@
   return DB;
 }
   
+/// \brief A partial diagnostic along with the source location where this
+/// diagnostic occurs.
+typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt;
 
 }  // end namespace clang
 #endif

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 12 18:32:35 2010
@@ -3266,6 +3266,10 @@
     /// \brief The number of template arguments in TemplateArgs.
     unsigned NumTemplateArgs;
 
+    /// \brief The template deduction info object associated with the 
+    /// substitution or checking of explicit or deduced template arguments.
+    sema::TemplateDeductionInfo *DeductionInfo;
+
     /// \brief The source range that covers the construct that cause
     /// the instantiation, e.g., the template-id that causes a class
     /// template instantiation.
@@ -3273,7 +3277,7 @@
 
     ActiveTemplateInstantiation()
       : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
-        NumTemplateArgs(0) {}
+        NumTemplateArgs(0), DeductionInfo(0) {}
 
     /// \brief Determines whether this template is an actual instantiation
     /// that should be counted toward the maximum instantiation depth.
@@ -3343,7 +3347,15 @@
   /// The top of this stack is used by a fixit instantiating unresolved
   /// function calls to fix the AST to match the textual change it prints.
   llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
-
+  
+  /// \brief For each declaration that involved template argument deduction, the
+  /// set of diagnostics that were suppressed during that template argument
+  /// deduction.
+  ///
+  /// FIXME: Serialize this structure to the AST file.
+  llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >
+    SuppressedDiagnostics;
+  
   /// \brief A stack object to be created when performing template
   /// instantiation.
   ///
@@ -3377,6 +3389,7 @@
                           const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs,
                           ActiveTemplateInstantiation::InstantiationKind Kind,
+                          sema::TemplateDeductionInfo &DeductionInfo,
                           SourceRange InstantiationRange = SourceRange());
 
     /// \brief Note that we are instantiating as part of template
@@ -3386,6 +3399,7 @@
                           ClassTemplatePartialSpecializationDecl *PartialSpec,
                           const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs,
+                          sema::TemplateDeductionInfo &DeductionInfo,
                           SourceRange InstantiationRange = SourceRange());
 
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -3432,7 +3446,6 @@
   private:
     Sema &SemaRef;
     bool Invalid;
-
     bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
                                  SourceRange InstantiationRange);
 
@@ -3448,9 +3461,11 @@
   /// template argument substitution failures are not considered
   /// errors.
   ///
-  /// When this routine returns true, the emission of most diagnostics
-  /// will be suppressed and there will be no local error recovery.
-  bool isSFINAEContext() const;
+  /// \returns The nearest template-deduction context object, if we are in a
+  /// SFINAE context, which can be used to capture diagnostics that will be
+  /// suppressed. Otherwise, returns NULL to indicate that we are not within a
+  /// SFINAE context.
+  sema::TemplateDeductionInfo *isSFINAEContext() const;
 
   /// \brief RAII class used to determine whether SFINAE has
   /// trapped any errors that occur during template argument

Modified: cfe/trunk/include/clang/Sema/TemplateDeduction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TemplateDeduction.h?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/TemplateDeduction.h (original)
+++ cfe/trunk/include/clang/Sema/TemplateDeduction.h Tue Oct 12 18:32:35 2010
@@ -13,7 +13,9 @@
 #ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
 #define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
 
+#include "clang/Basic/PartialDiagnostic.h"
 #include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 
@@ -21,7 +23,7 @@
 class TemplateArgumentList;
 
 namespace sema {
-
+  
 /// \brief Provides information about an attempted template argument
 /// deduction, whose success or failure was described by a
 /// TemplateDeductionResult value.
@@ -37,6 +39,10 @@
   /// deduction is occurring.
   SourceLocation Loc;
 
+  /// \brief Warnings (and follow-on notes) that were suppressed due to 
+  /// SFINAE while performing template argument deduction.
+  llvm::SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
+  
   // do not implement these
   TemplateDeductionInfo(const TemplateDeductionInfo&);
   TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
@@ -69,6 +75,23 @@
     Deduced = NewDeduced;
   }
 
+  /// \brief Add a new diagnostic to the set of diagnostics 
+  void addSuppressedDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+    SuppressedDiagnostics.push_back(std::make_pair(Loc, PD));
+  }
+  
+  /// \brief Iterator over the set of suppressed diagnostics.
+  typedef llvm::SmallVectorImpl<PartialDiagnosticAt>::const_iterator 
+    diag_iterator;
+  
+  /// \brief Returns an iterator at the beginning of the sequence of suppressed
+  /// diagnostics.
+  diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
+  
+  /// \brief Returns an iterator at the end of the sequence of suppressed
+  /// diagnostics.
+  diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
+  
   /// \brief The template parameter to which a template argument
   /// deduction failure refers.
   ///

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Tue Oct 12 18:32:35 2010
@@ -19,6 +19,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/APFloat.h"
 #include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/TemplateDeduction.h"
 #include "clang/Sema/ExternalSemaSource.h"
 #include "clang/Sema/ObjCMethodList.h"
 #include "clang/Sema/PrettyDeclStackTrace.h"
@@ -433,6 +434,41 @@
 }
 
 Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
+  if (!isActive())
+    return;
+  
+  if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) {
+    switch (Diagnostic::getDiagnosticSFINAEResponse(getDiagID())) {
+    case Diagnostic::SFINAE_Report:
+      // Fall through; we'll report the diagnostic below.
+      break;
+      
+    case Diagnostic::SFINAE_SubstitutionFailure:
+      // Count this failure so that we know that template argument deduction
+      // has failed.
+      ++SemaRef.NumSFINAEErrors;
+      SemaRef.Diags.setLastDiagnosticIgnored();
+      SemaRef.Diags.Clear();
+      Clear();
+      return;
+      
+    case Diagnostic::SFINAE_Suppress:
+      // Make a copy of this suppressed diagnostic and store it with the
+      // template-deduction information;
+      DiagnosticInfo DiagInfo(&SemaRef.Diags);
+      Info->addSuppressedDiagnostic(DiagInfo.getLocation(),
+                        PartialDiagnostic(DiagInfo,
+                                          SemaRef.Context.getDiagAllocator()));
+        
+      // Suppress this diagnostic.        
+      SemaRef.Diags.setLastDiagnosticIgnored();
+      SemaRef.Diags.Clear();
+      Clear();
+      return;
+    }
+  }
+  
+  // Emit the diagnostic.
   if (!this->Emit())
     return;
 
@@ -451,25 +487,6 @@
 }
 
 Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) {
-  if (isSFINAEContext()) {
-    switch (Diagnostic::getDiagnosticSFINAEResponse(DiagID)) {
-    case Diagnostic::SFINAE_Report:
-      // Fall through; we'll report the diagnostic below.
-      break;
-
-    case Diagnostic::SFINAE_SubstitutionFailure:
-      // Count this failure so that we know that template argument deduction
-      // has failed.
-      ++NumSFINAEErrors;
-      // Fall through
-        
-    case Diagnostic::SFINAE_Suppress:
-      // Suppress this diagnostic.
-      Diags.setLastDiagnosticIgnored();
-      return SemaDiagnosticBuilder(*this);
-    }
-  }
-  
   DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
   return SemaDiagnosticBuilder(DB, *this, DiagID);
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Oct 12 18:32:35 2010
@@ -56,6 +56,24 @@
 /// referenced), false otherwise.
 ///
 bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
+  if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
+    // If there were any diagnostics suppressed by template argument deduction,
+    // emit them now.
+    llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+      Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+    if (Pos != SuppressedDiagnostics.end()) {
+      llvm::SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
+      for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
+        Diag(Suppressed[I].first, Suppressed[I].second);
+      
+      // Clear out the list of suppressed diagnostics, so that we don't emit
+      // them again for this specialization. However, we don't remove this
+      // entry from the table, because we want to avoid ever emitting these
+      // diagnostics again.
+      Suppressed.clear();
+    }
+  }
+
   // See if the decl is deprecated.
   if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
     EmitDeprecationWarning(D, DA->getMessage(), Loc);

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Oct 12 18:32:35 2010
@@ -1551,9 +1551,11 @@
         return ExprError();
       
       if (!RD->hasTrivialDestructor())
-        if (const CXXDestructorDecl *Dtor = LookupDestructor(RD))
+        if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
           MarkDeclarationReferenced(StartLoc,
                                     const_cast<CXXDestructorDecl*>(Dtor));
+          DiagnoseUseOfDecl(Dtor, StartLoc);
+        }
     }
     
     if (!OperatorDelete) {
@@ -1829,7 +1831,7 @@
 
     if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
       return true;
-
+    
     From = FixOverloadedFunctionReference(From, Found, Fn);
     FromType = From->getType();
   }

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Oct 12 18:32:35 2010
@@ -3765,6 +3765,7 @@
           S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, 
                                   S.PDiag(diag::err_access_dtor_temp) << T);
           S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
+          S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart());
         }
       }
       
@@ -3858,7 +3859,8 @@
         unsigned NumExprs = ConstructorArgs.size();
         Expr **Exprs = (Expr **)ConstructorArgs.take();
         S.MarkDeclarationReferenced(Loc, Constructor);
-            
+        S.DiagnoseUseOfDecl(Constructor, Loc);
+    
         TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
         if (!TSInfo)
           TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Oct 12 18:32:35 2010
@@ -5489,6 +5489,7 @@
   //   placement new (5.3.4), as well as non-default initialization (8.5).
   if (Best->Function)
     S.MarkDeclarationReferenced(Loc, Best->Function);
+  
   return OR_Success;
 }
 
@@ -6313,7 +6314,7 @@
   // whose type matches exactly.
   llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
   llvm::SmallVector<FunctionDecl *, 4> NonMatches;
-
+  
   bool FoundNonTemplateFunction = false;
   for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
          E = OvlExpr->decls_end(); I != E; ++I) {
@@ -6344,7 +6345,6 @@
       //   resulting template argument list is used to generate a single
       //   function template specialization, which is added to the set of
       //   overloaded functions considered.
-      // FIXME: We don't really want to build the specialization here, do we?
       FunctionDecl *Specialization = 0;
       TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
       if (TemplateDeductionResult Result
@@ -6355,10 +6355,10 @@
       } else {
         // Template argument deduction ensures that we have an exact match.
         // This function template specicalization works.
+        Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
         assert(FunctionType
                  == Context.getCanonicalType(Specialization->getType()));
-        Matches.push_back(std::make_pair(I.getPair(),
-                    cast<FunctionDecl>(Specialization->getCanonicalDecl())));
+        Matches.push_back(std::make_pair(I.getPair(), Specialization));
       }
 
       continue;
@@ -6403,10 +6403,11 @@
     return 0;
   } else if (Matches.size() == 1) {
     FunctionDecl *Result = Matches[0].second;
-    FoundResult = Matches[0].first;
+    FoundResult = Matches[0].first;    
     MarkDeclarationReferenced(From->getLocStart(), Result);
-    if (Complain)
+    if (Complain) {
       CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
+    }
     return Result;
   }
 
@@ -6441,10 +6442,8 @@
     
     MarkDeclarationReferenced(From->getLocStart(), *Result);
     FoundResult = Matches[Result - MatchesCopy.begin()].first;
-    if (Complain) {
+    if (Complain)
       CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
-      DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc());
-    }
     return cast<FunctionDecl>(*Result);
   }
 
@@ -6464,10 +6463,8 @@
   if (Matches.size() == 1) {
     MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
     FoundResult = Matches[0].first;
-    if (Complain) {
+    if (Complain)
       CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
-      DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc());
-    }
     return cast<FunctionDecl>(Matches[0].second);
   }
 
@@ -6543,7 +6540,7 @@
 
     Matched = Specialization;
   }
-
+  
   return Matched;
 }
     
@@ -6734,7 +6731,7 @@
   case OR_Success: {
     FunctionDecl *FDecl = Best->Function;
     CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
-    DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc());
+    DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl, ULE->getNameLoc());
     Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
     return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
   }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Oct 12 18:32:35 2010
@@ -2363,6 +2363,9 @@
   //   template-argument for a template type-parameter.
   // C++0x allows these, and even in C++03 we allow them as an extension with
   // a warning.
+  //
+  // FIXME: We're not handling the "type compounded from any of these types"
+  // case.
   SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
   if (!LangOpts.CPlusPlus0x) {
     const TagType *Tag = 0;

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Oct 12 18:32:35 2010
@@ -1127,7 +1127,7 @@
     return Result;
 
   InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
-                             Deduced.data(), Deduced.size());
+                             Deduced.data(), Deduced.size(), Info);
   if (Inst)
     return TDK_InstantiationDepth;
 
@@ -1214,7 +1214,8 @@
   // and then substitute them into the function parameter types.
   InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
                              FunctionTemplate, Deduced.data(), Deduced.size(),
-           ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
+           ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
+                             Info);
   if (Inst)
     return TDK_InstantiationDepth;
 
@@ -1374,7 +1375,8 @@
   // actual function declaration.
   InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
                              FunctionTemplate, Deduced.data(), Deduced.size(),
-              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+                             Info);
   if (Inst)
     return TDK_InstantiationDepth;
 
@@ -1429,7 +1431,7 @@
       TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this,
                                                               Deduced[I],
                                                               NTTPType,
-                                                           SourceLocation());
+                                                            Info.getLocation());
 
       // Check the template argument, converting it as necessary.
       if (CheckTemplateArgument(Param, Arg,
@@ -1515,6 +1517,18 @@
     return TDK_SubstitutionFailure;
   }
 
+  // If we suppressed any diagnostics while performing template argument
+  // deduction, and if we haven't already instantiated this declaration,
+  // keep track of these diagnostics. They'll be emitted if this specialization
+  // is actually used.
+  if (Info.diag_begin() != Info.diag_end()) {
+    llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+      Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
+    if (Pos == SuppressedDiagnostics.end())
+        SuppressedDiagnostics[Specialization->getCanonicalDecl()]
+          .append(Info.diag_begin(), Info.diag_end());
+  }                                                               
+
   return TDK_Success;
 }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Oct 12 18:32:35 2010
@@ -148,7 +148,6 @@
                       Decl *Entity,
                       SourceRange InstantiationRange)
   :  SemaRef(SemaRef) {
-
   Invalid = CheckInstantiationDepth(PointOfInstantiation,
                                     InstantiationRange);
   if (!Invalid) {
@@ -192,6 +191,7 @@
                                         const TemplateArgument *TemplateArgs,
                                                    unsigned NumTemplateArgs,
                          ActiveTemplateInstantiation::InstantiationKind Kind,
+                                   sema::TemplateDeductionInfo &DeductionInfo,
                                               SourceRange InstantiationRange)
 : SemaRef(SemaRef) {
 
@@ -204,6 +204,7 @@
     Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
     Inst.TemplateArgs = TemplateArgs;
     Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.DeductionInfo = &DeductionInfo;
     Inst.InstantiationRange = InstantiationRange;
     SemaRef.ActiveTemplateInstantiations.push_back(Inst);
     
@@ -217,6 +218,7 @@
                           ClassTemplatePartialSpecializationDecl *PartialSpec,
                                          const TemplateArgument *TemplateArgs,
                                          unsigned NumTemplateArgs,
+                                    sema::TemplateDeductionInfo &DeductionInfo,
                                          SourceRange InstantiationRange)
   : SemaRef(SemaRef) {
 
@@ -228,6 +230,7 @@
   Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
   Inst.TemplateArgs = TemplateArgs;
   Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.DeductionInfo = &DeductionInfo;
   Inst.InstantiationRange = InstantiationRange;
   SemaRef.ActiveTemplateInstantiations.push_back(Inst);
       
@@ -516,7 +519,7 @@
   }
 }
 
-bool Sema::isSFINAEContext() const {
+TemplateDeductionInfo *Sema::isSFINAEContext() const {
   using llvm::SmallVector;
   for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
          Active = ActiveTemplateInstantiations.rbegin(),
@@ -528,7 +531,7 @@
     case ActiveTemplateInstantiation::TemplateInstantiation:
     case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
       // This is a template instantiation, so there is no SFINAE.
-      return false;
+      return 0;
 
     case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
     case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
@@ -542,11 +545,12 @@
     case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
       // We're either substitution explicitly-specified template arguments
       // or deduced template arguments, so SFINAE applies.
-      return true;
+      assert(Active->DeductionInfo && "Missing deduction info pointer");
+      return Active->DeductionInfo;
     }
   }
 
-  return false;
+  return 0;
 }
 
 //===----------------------------------------------------------------------===/
@@ -1255,6 +1259,16 @@
   return Invalid;
 }
 
+namespace {
+  /// \brief A partial specialization whose template arguments have matched
+  /// a given template-id.
+  struct PartialSpecMatchResult {
+    ClassTemplatePartialSpecializationDecl *Partial;
+    TemplateArgumentList *Args;
+    llvm::SmallVector<PartialDiagnosticAt, 1> Diagnostics;
+  };
+}
+
 bool
 Sema::InstantiateClassTemplateSpecialization(
                            SourceLocation PointOfInstantiation,
@@ -1304,8 +1318,7 @@
   //   matching the template arguments of the class template
   //   specialization with the template argument lists of the partial
   //   specializations.
-  typedef std::pair<ClassTemplatePartialSpecializationDecl *,
-                    TemplateArgumentList *> MatchResult;
+  typedef PartialSpecMatchResult MatchResult;
   llvm::SmallVector<MatchResult, 4> Matched;
   llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
   Template->getPartialSpecializations(PartialSpecs);
@@ -1320,7 +1333,10 @@
       // diagnostics, later.
       (void)Result;
     } else {
-      Matched.push_back(std::make_pair(Partial, Info.take()));
+      Matched.push_back(PartialSpecMatchResult());
+      Matched.back().Partial = Partial;
+      Matched.back().Args = Info.take();
+      Matched.back().Diagnostics.append(Info.diag_begin(), Info.diag_end());
     }
   }
 
@@ -1341,9 +1357,9 @@
       for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
                                                     PEnd = Matched.end();
            P != PEnd; ++P) {
-        if (getMoreSpecializedPartialSpecialization(P->first, Best->first,
+        if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
                                                     PointOfInstantiation) 
-              == P->first)
+              == P->Partial)
           Best = P;
       }
       
@@ -1354,9 +1370,9 @@
                                                     PEnd = Matched.end();
            P != PEnd; ++P) {
         if (P != Best &&
-            getMoreSpecializedPartialSpecialization(P->first, Best->first,
+            getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
                                                     PointOfInstantiation)
-              != Best->first) {
+              != Best->Partial) {
           Ambiguous = true;
           break;
         }
@@ -1372,16 +1388,17 @@
         for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
                                                       PEnd = Matched.end();
              P != PEnd; ++P)
-          Diag(P->first->getLocation(), diag::note_partial_spec_match)
-            << getTemplateArgumentBindingsText(P->first->getTemplateParameters(),
-                                               *P->second);
+          Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+            << getTemplateArgumentBindingsText(
+                                            P->Partial->getTemplateParameters(),
+                                               *P->Args);
 
         return true;
       }
     }
     
     // Instantiate using the best class template partial specialization.
-    ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first;
+    ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
     while (OrigPartialSpec->getInstantiatedFromMember()) {
       // If we've found an explicit specialization of this class template,
       // stop here and use that as the pattern.
@@ -1392,7 +1409,11 @@
     }
     
     Pattern = OrigPartialSpec;
-    ClassTemplateSpec->setInstantiationOf(Best->first, Best->second);
+    ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+    
+    // Report any suppressed diagnostics.
+    for (unsigned I = 0, N = Best->Diagnostics.size(); I != N; ++I)
+      Diag(Best->Diagnostics[I].first, Best->Diagnostics[I].second);
   } else {
     //   -- If no matches are found, the instantiation is generated
     //      from the primary template.

Modified: cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp?rev=116373&r1=116372&r2=116373&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp Tue Oct 12 18:32:35 2010
@@ -11,11 +11,32 @@
 B<function> b; // expected-note{{instantiation of}}
 
 template <typename T> int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}}
-enum {e};
+enum {e}; // expected-note{{unnamed type used in template argument was declared here}}
 
 void test_f0(int n) {
-  int i = f0(0, e); // FIXME: We should get a warning here, at least
+  int i = f0(0, e); // expected-warning{{template argument uses unnamed type}}
   int vla[n];
   f0(0, vla); // expected-error{{no matching function for call to 'f0'}}
 }
 
+namespace N0 {
+  template <typename R, typename A1> void f0(R (*)(A1));
+  template <typename T> int f1(T);
+  template <typename T, typename U> int f1(T, U);
+  enum {e1}; // expected-note 2{{unnamed type used in template argument was declared here}}
+  enum {e2}; // expected-note 2{{unnamed type used in template argument was declared here}}
+  enum {e3}; // FIXME: expected unnamed type used in template argument was declared here
+
+  template<typename T> struct X;
+  template<typename T> struct X<T*> { };
+
+  void f() {
+    f0( // expected-warning{{template argument uses unnamed type}}
+       &f1<__typeof__(e1)>); // expected-warning{{template argument uses unnamed type}}
+    int (*fp1)(int, __typeof__(e2)) = f1; // expected-warning{{template argument uses unnamed type}}
+    f1(e2); // expected-warning{{template argument uses unnamed type}}
+    f1(e2);
+
+    X<__typeof__(e3)*> x; // FIXME: should warn about unnamed type
+  }
+}





More information about the cfe-commits mailing list