[cfe-commits] r127521 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseExprCXX.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/SemaTemplate/resolve-single-template-id.patch

Douglas Gregor dgregor at apple.com
Fri Mar 11 17:48:57 PST 2011


Author: dgregor
Date: Fri Mar 11 19:48:56 2011
New Revision: 127521

URL: http://llvm.org/viewvc/llvm-project?rev=127521&view=rev
Log:
Fixes for some more expressions containing function templateids that
should be resolvable, from Faisal Vali!

Added:
    cfe/trunk/test/SemaTemplate/resolve-single-template-id.patch
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=127521&r1=127520&r2=127521&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 11 19:48:56 2011
@@ -1289,6 +1289,14 @@
                                                    bool Complain = false,
                                                    DeclAccessPair* Found = 0);
 
+  ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
+                      Expr *SrcExpr, bool DoFunctionPointerConverion = false, 
+                      bool Complain = false, 
+                      const SourceRange& OpRangeForComplaining = SourceRange(), 
+                      QualType DestTypeForComplaining = QualType(), 
+                      unsigned DiagIDForComplaining = 0);
+
+
   Expr *FixOverloadedFunctionReference(Expr *E,
                                        DeclAccessPair FoundDecl,
                                        FunctionDecl *Fn);

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=127521&r1=127520&r2=127521&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Mar 11 19:48:56 2011
@@ -527,7 +527,15 @@
       RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
       if (RParenLoc.isInvalid())
         return ExprError();
-      
+
+      // If we are a foo<int> that identifies a single function, resolve it now...  
+      Expr* e = Result.get();
+      if (e->getType() == Actions.Context.OverloadTy) {
+        ExprResult er = 
+              Actions.ResolveAndFixSingleFunctionTemplateSpecialization(e);
+        if (er.isUsable())
+          Result = er.release();
+      }
       Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
                                       Result.release(), RParenLoc);
     }

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=127521&r1=127520&r2=127521&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Fri Mar 11 19:48:56 2011
@@ -128,17 +128,6 @@
                                         CastKind &Kind);
 
 
-static ExprResult 
-ResolveAndFixSingleFunctionTemplateSpecialization(
-                    Sema &Self, Expr *SrcExpr, 
-                    bool DoFunctionPointerConverion = false, 
-                    bool Complain = false, 
-                    const SourceRange& OpRangeForComplaining = SourceRange(), 
-                    QualType DestTypeForComplaining = QualType(), 
-                    unsigned DiagIDForComplaining = 0);
-
-
-
 /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
 ExprResult
 Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
@@ -617,7 +606,7 @@
     Self.IgnoredValueConversions(SrcExpr);
     if (SrcExpr->getType() == Self.Context.OverloadTy) {
       ExprResult SingleFunctionExpression = 
-         ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, 
+         Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, 
                 false, // Decay Function to ptr 
                 true, // Complain
                 OpRange, DestType, diag::err_bad_static_cast_overload);
@@ -1260,41 +1249,8 @@
   return TC_Success;
 }
 
-// A helper function to resolve and fix an overloaded expression that
-// can be resolved because it identifies a single function
-// template specialization
-// Last three arguments should only be supplied if Complain = true
-static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
-                    Sema &Self, Expr *SrcExpr, 
-                    bool DoFunctionPointerConverion, 
-                    bool Complain, 
-                    const SourceRange& OpRangeForComplaining, 
-                    QualType DestTypeForComplaining, 
-                    unsigned DiagIDForComplaining) {
-  assert(SrcExpr->getType() == Self.Context.OverloadTy);
-  DeclAccessPair Found;
-  Expr* SingleFunctionExpression = 0;
-  if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization(
-                                    SrcExpr, false, // false -> Complain 
-                                    &Found)) {
-    if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
-      // mark the expression as resolved to Fn
-      SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr, 
-                                                                    Found, Fn);
-      
-      if (DoFunctionPointerConverion)
-        Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression);
-    }      
-  }
-  if (!SingleFunctionExpression && Complain) {
-    OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
-    Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
-      << oe->getName() << DestTypeForComplaining << OpRangeForComplaining 
-      << oe->getQualifierLoc().getSourceRange();
-    Self.NoteAllOverloadCandidates(SrcExpr);
-  }
-  return SingleFunctionExpression;
-}
+
+
 
 static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
                                         QualType DestType, bool CStyle,
@@ -1311,7 +1267,7 @@
   if (SrcType == Self.Context.OverloadTy) {
     // ... unless foo<int> resolves to an lvalue unambiguously
     ExprResult SingleFunctionExpr = 
-        ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, 
+        Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, 
           Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr 
         );
     if (SingleFunctionExpr.isUsable()) {
@@ -1544,11 +1500,11 @@
     bool ret = false; // false is 'able to convert'
     if (CastExpr->getType() == Context.OverloadTy) {
       ExprResult SingleFunctionExpr = 
-        ResolveAndFixSingleFunctionTemplateSpecialization(*this, 
-              CastExpr, 
-              /* Decay Function to ptr */ false, 
-              /* Complain */ true, 
-              R, CastTy, diag::err_bad_cstyle_cast_overload);
+        ResolveAndFixSingleFunctionTemplateSpecialization(
+                  CastExpr, /* Decay Function to ptr */ false, 
+                  /* Complain */ true, R, CastTy, 
+                  diag::err_bad_cstyle_cast_overload);
+
       if (SingleFunctionExpr.isUsable()) {
         CastExpr = SingleFunctionExpr.release();
         Kind = CK_ToVoid;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=127521&r1=127520&r2=127521&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 11 19:48:56 2011
@@ -5321,9 +5321,10 @@
 QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
                                         ExprValueKind &VK, ExprObjectKind &OK,
                                         SourceLocation QuestionLoc) {
-  // If both LHS and RHS are overloaded functions, try to resolve them.
-  if (Context.hasSameType(LHS->getType(), RHS->getType()) && 
-      LHS->getType()->isSpecificBuiltinType(BuiltinType::Overload)) {
+
+  // If either LHS or RHS are overloaded functions, try to resolve them.
+  if (LHS->getType() == Context.OverloadTy || 
+      RHS->getType() == Context.OverloadTy) {
     ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc);
     if (LHSResult.isInvalid())
       return QualType();
@@ -6313,6 +6314,10 @@
   Diag(Loc, diag::err_typecheck_invalid_operands)
     << lex->getType() << rex->getType()
     << lex->getSourceRange() << rex->getSourceRange();
+    if (lex->getType() == Context.OverloadTy)
+      NoteAllOverloadCandidates(lex);
+    if (rex->getType() == Context.OverloadTy)
+      NoteAllOverloadCandidates(rex);
   return QualType();
 }
 
@@ -6789,12 +6794,14 @@
 
   QualType lType = lex->getType();
   QualType rType = rex->getType();
-
+ 
   Expr *LHSStripped = lex->IgnoreParenImpCasts();
   Expr *RHSStripped = rex->IgnoreParenImpCasts();
   QualType LHSStrippedType = LHSStripped->getType();
   QualType RHSStrippedType = RHSStripped->getType();
 
+  
+
   // Two different enums will raise a warning when compared.
   if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) {
     if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) {
@@ -8033,6 +8040,26 @@
   ExprValueKind VK = VK_RValue;
   ExprObjectKind OK = OK_Ordinary;
 
+  // Check if a 'foo<int>' involved in a binary op, identifies a single 
+  // function unambiguously (i.e. an lvalue ala 13.4)
+  // But since an assignment can trigger target based overload, exclude it in 
+  // our blind search. i.e:
+  // template<class T> void f(); template<class T, class U> void f(U);
+  // f<int> == 0;  // resolve f<int> blindly
+  // void (*p)(int); p = f<int>;  // resolve f<int> using target
+  if (Opc != BO_Assign) { 
+    if (lhs->getType() == Context.OverloadTy) {
+      ExprResult resolvedLHS = 
+        ResolveAndFixSingleFunctionTemplateSpecialization(lhs);
+      if (resolvedLHS.isUsable()) lhs = resolvedLHS.release(); 
+    }
+    if (rhs->getType() == Context.OverloadTy) {
+      ExprResult resolvedRHS = 
+        ResolveAndFixSingleFunctionTemplateSpecialization(rhs);
+      if (resolvedRHS.isUsable()) rhs = resolvedRHS.release(); 
+    }
+  }
+
   switch (Opc) {
   case BO_Assign:
     ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
@@ -8390,6 +8417,11 @@
     resultType = CheckAddressOfOperand(*this, Input, OpLoc);
     break;
   case UO_Deref:
+    if (Input->getType() == Context.OverloadTy ) {
+      ExprResult er = ResolveAndFixSingleFunctionTemplateSpecialization(Input);
+      if (er.isUsable())
+        Input = er.release();
+    }
     DefaultFunctionArrayLvalueConversion(Input);
     resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc);
     break;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=127521&r1=127520&r2=127521&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Mar 11 19:48:56 2011
@@ -7490,6 +7490,44 @@
   return Matched;
 }
 
+
+
+
+// Resolve and fix an overloaded expression that
+// can be resolved because it identifies a single function
+// template specialization
+// Last three arguments should only be supplied if Complain = true
+ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
+             Expr *SrcExpr, bool DoFunctionPointerConverion, bool Complain,
+                                  const SourceRange& OpRangeForComplaining, 
+                                           QualType DestTypeForComplaining, 
+                                            unsigned DiagIDForComplaining ) {
+
+    assert(SrcExpr->getType() == Context.OverloadTy);
+
+    DeclAccessPair Found;
+    Expr* SingleFunctionExpression = 0;
+    if (FunctionDecl* Fn = ResolveSingleFunctionTemplateSpecialization(
+      SrcExpr, false, // false -> Complain 
+      &Found)) {
+        if (!DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
+          // mark the expression as resolved to Fn
+          SingleFunctionExpression = FixOverloadedFunctionReference(SrcExpr, 
+            Found, Fn);
+          if (DoFunctionPointerConverion)
+            DefaultFunctionArrayLvalueConversion(SingleFunctionExpression);
+        }      
+    }
+    if (!SingleFunctionExpression && Complain) {
+      OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
+      Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+        << oe->getName() << DestTypeForComplaining << OpRangeForComplaining 
+        << oe->getQualifierLoc().getSourceRange();
+      NoteAllOverloadCandidates(SrcExpr);
+    }
+    return SingleFunctionExpression;
+}
+
 /// \brief Add a single candidate to the overload set.
 static void AddOverloadedCallCandidate(Sema &S,
                                        DeclAccessPair FoundDecl,

Added: cfe/trunk/test/SemaTemplate/resolve-single-template-id.patch
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/resolve-single-template-id.patch?rev=127521&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/resolve-single-template-id.patch (added)
+++ cfe/trunk/test/SemaTemplate/resolve-single-template-id.patch Fri Mar 11 19:48:56 2011
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+//#include <typeinfo>
+void one() { }
+void two() { } // expected-note 3{{candidate}}
+void two(int) { } // expected-note 3{{candidate}}
+
+template<class T> void twoT() { } // expected-note 4{{candidate}}
+template<class T> void twoT(int) { } // expected-note 4{{candidate}}
+
+template<class T> void oneT() { }
+template<class T, class U> void oneT(U) { }
+/*
+The target can be
+ an object or reference being initialized (8.5, 8.5.3),
+ the left side of an assignment (5.17),
+ a parameter of a function (5.2.2),
+ a parameter of a user-defined operator (13.5),
+ the return value of a function, operator function, or conversion (6.6.3),
+ an explicit type conversion (5.2.3, 5.2.9, 5.4), or
+ a non-type template-parameter (14.3.2)
+*/
+//#include <typeinfo>
+template<void (*p)(int)> struct test { };
+
+int main()
+{
+   one;         // expected-warning {{expression result unused}}
+   two;         // expected-error {{address of overloaded}}
+   oneT<int>;  // expected-warning {{expression result unused}}
+   twoT<int>;  // expected-error {{address of overloaded}}
+  typeid(oneT<int>); //expected-error {{you need to include <typeinfo>}}
+  sizeof(oneT<int>); // expected-warning {{expression result unused}}
+  sizeof(twoT<int>); //expected-error {{cannot resolve overloaded function from context}}
+  decltype(oneT<int>)* fun = 0;
+  
+  *one;    // expected-warning {{expression result unused}}
+  *oneT<int>;   // expected-warning {{expression result unused}}
+  *two;  //expected-error {{cannot resolve overloaded function from context}}
+  *twoT<int>; //expected-error {{cannot resolve overloaded function from context}}
+  !oneT<int>;  // expected-warning {{expression result unused}}
+  +oneT<int>;  // expected-warning {{expression result unused}}
+  -oneT<int>;  //expected-error {{invalid argument type}}
+  oneT<int> == 0;   // expected-warning {{expression result unused}}
+  0 == oneT<int>;   // expected-warning {{expression result unused}}
+  0 != oneT<int>;    // expected-warning {{expression result unused}}
+  (false ? one : oneT<int>);   // expected-warning {{expression result unused}}
+  void (*p1)(int); p1 = oneT<int>;
+  
+  int i = (int) (false ? (void (*)(int))twoT<int> : oneT<int>); //expected-error {{incompatible operand}}
+  (twoT<int>) == oneT<int>; //expected-error {{invalid operands to binary expression}}
+  bool b = oneT<int>;
+  void (*p)() = oneT<int>;
+  test<oneT<int>> ti;
+  void (*u)(int) = oneT<int>;
+
+  b = (void (*)()) twoT<int>;
+  
+  one < one; //expected-warning {{self-comparison always evaluates to false}} \
+             //expected-warning {{expression result unused}}         
+
+  oneT<int> < oneT<int>;  //expected-warning {{self-comparison always evaluates to false}} \
+                          //expected-warning {{expression result unused}}
+
+  two < two; //expected-error {{invalid operands to binary expression}}
+  twoT<int> < twoT<int>; //expected-error {{invalid operands to binary expression}}
+  oneT<int> == 0;   // expected-warning {{expression result unused}}
+
+}





More information about the cfe-commits mailing list