From: Sebastian Redl Date: Sat, 17 Oct 2009 20:50:27 +0000 (+0000) Subject: Don't add implicit casts of explicit address-taking of overloaded functions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=759986e85990281ea741820822809ac57fd28c40;p=clang Don't add implicit casts of explicit address-taking of overloaded functions. Taking the address of an overloaded function with an explicit address-of operator wrapped the operator in an implicit cast that added yet another pointer level, leaving us with a corrupted AST, which crashed CodeGen in the test case I've added. Fix this by making FixOverloadedFunctionReference return whether there was an address-of operator and not adding the implicit cast in that case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84362 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 8ebe5ef6fc..1cadcecd88 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -929,7 +929,7 @@ public: FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, bool Complain); - void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); + bool FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); void AddOverloadedCallCandidates(NamedDecl *Callee, DeclarationName &UnqualifiedName, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7fc27a44f7..d56c426d00 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1222,8 +1222,13 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) return true; - FixOverloadedFunctionReference(From, Fn); + bool WasAddrOf = FixOverloadedFunctionReference(From, Fn); FromType = From->getType(); + // If there's already an address-of operator in the expression, we have + // the right type already, and the code below would just introduce an + // invalid additional pointer level. + if (WasAddrOf) + break; } FromType = Context.getPointerType(FromType); ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ecadcd904e..5f874e8dbc 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5300,10 +5300,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { /// perhaps a '&' around it). We have resolved the overloaded function /// to the function declaration Fn, so patch up the expression E to /// refer (possibly indirectly) to Fn. -void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { +/// Returns true if the function reference used an explicit address-of operator. +bool Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast(E)) { - FixOverloadedFunctionReference(PE->getSubExpr(), Fn); + bool ret = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); E->setType(PE->getSubExpr()->getType()); + return ret; } else if (UnaryOperator *UnOp = dyn_cast(E)) { assert(UnOp->getOpcode() == UnaryOperator::AddrOf && "Can only take the address of an overloaded function"); @@ -5322,11 +5324,12 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { = Context.getTypeDeclType(cast(Method->getDeclContext())); E->setType(Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr())); - return; + return true; } } FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); E->setType(Context.getPointerType(UnOp->getSubExpr()->getType())); + return true; } else if (DeclRefExpr *DR = dyn_cast(E)) { assert((isa(DR->getDecl()) || isa(DR->getDecl())) && @@ -5339,6 +5342,7 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { } else { assert(false && "Invalid reference to overloaded function"); } + return false; } } // end namespace clang diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp new file mode 100644 index 0000000000..cbf042551d --- /dev/null +++ b/test/CodeGenCXX/address-of-fntemplate.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s +template void f(T) {} + +void test() { + // FIXME: This emits only a declaration instead of a definition + // CHECK: @_Z1fIiEvT_ + void (*p)(int) = &f; +} +// CHECK-disabled: define linkonce_odr void @_Z1fIiEvT_