[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