From: Aaron Ballman Date: Fri, 2 Sep 2016 13:45:40 +0000 (+0000) Subject: Allow a C11 generic selection expression to select a function with the overloadable... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7453511ad2de56589b4ef083bcb875a9d9d62b2e;p=clang Allow a C11 generic selection expression to select a function with the overloadable attribute as the result expression without crashing. This fixes PR30201. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280483 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 7f98f005fe..53e8f7bec7 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -4447,11 +4447,19 @@ public: return cast(SubExprs[END_EXPR+i]); } Expr *getAssocExpr(unsigned i) { return cast(SubExprs[END_EXPR+i]); } - + ArrayRef getAssocExprs() const { + return NumAssocs + ? llvm::makeArrayRef( + &reinterpret_cast(SubExprs)[END_EXPR], NumAssocs) + : None; + } const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { return AssocTypes[i]; } TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + ArrayRef getAssocTypeSourceInfos() const { + return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None; + } QualType getAssocType(unsigned i) const { if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 72ad9a4d71..36643812b0 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -12984,6 +12984,31 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, ICE->getValueKind()); } + if (auto *GSE = dyn_cast(E)) { + if (!GSE->isResultDependent()) { + Expr *SubExpr = + FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn); + if (SubExpr == GSE->getResultExpr()) + return GSE; + + // Replace the resulting type information before rebuilding the generic + // selection expression. + SmallVector AssocExprs(GSE->getAssocExprs().begin(), + GSE->getAssocExprs().end()); + unsigned ResultIdx = GSE->getResultIndex(); + AssocExprs[ResultIdx] = SubExpr; + + return new (Context) GenericSelectionExpr( + Context, GSE->getGenericLoc(), GSE->getControllingExpr(), + GSE->getAssocTypeSourceInfos(), AssocExprs, GSE->getDefaultLoc(), + GSE->getRParenLoc(), GSE->containsUnexpandedParameterPack(), + ResultIdx); + } + // Rather than fall through to the unreachable, return the original generic + // selection expression. + return GSE; + } + if (UnaryOperator *UnOp = dyn_cast(E)) { assert(UnOp->getOpcode() == UO_AddrOf && "Can only take the address of an overloaded function"); diff --git a/test/Sema/generic-selection.c b/test/Sema/generic-selection.c index 5c02005d0f..9829958305 100644 --- a/test/Sema/generic-selection.c +++ b/test/Sema/generic-selection.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c1x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s void g(void); @@ -36,3 +36,11 @@ void foo(int n) { // expression is not evaluated. (void)_Generic(*(int *)0, int: 1); } + +int __attribute__((overloadable)) test (int); +double __attribute__((overloadable)) test (double); +char testc(char); + +void PR30201(void) { + _Generic(4, char:testc, default:test)(4); +}