diff options
| author | Aaron Ballman <aaron@aaronballman.com> | 2016-09-02 13:45:40 +0000 |
|---|---|---|
| committer | Aaron Ballman <aaron@aaronballman.com> | 2016-09-02 13:45:40 +0000 |
| commit | ff7bd8bacd13019529b7709efa95ae834c4537a4 (patch) | |
| tree | ff511e9235c978455b7449545dbefa7a2d123ae0 | |
| parent | fd503e5af306b6aad3dd3d7005ff86e008aad2dd (diff) | |
| download | bcm5719-llvm-ff7bd8bacd13019529b7709efa95ae834c4537a4.tar.gz bcm5719-llvm-ff7bd8bacd13019529b7709efa95ae834c4537a4.zip | |
Allow a C11 generic selection expression to select a function with the overloadable attribute as the result expression without crashing. This fixes PR30201.
llvm-svn: 280483
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 25 | ||||
| -rw-r--r-- | clang/test/Sema/generic-selection.c | 10 |
3 files changed, 43 insertions, 2 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 7f98f005feb..53e8f7bec73 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4447,11 +4447,19 @@ public: return cast<Expr>(SubExprs[END_EXPR+i]); } Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); } - + ArrayRef<Expr *> getAssocExprs() const { + return NumAssocs + ? llvm::makeArrayRef( + &reinterpret_cast<Expr **>(SubExprs)[END_EXPR], NumAssocs) + : None; + } const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { return AssocTypes[i]; } TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const { + return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None; + } QualType getAssocType(unsigned i) const { if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 72ad9a4d715..36643812b02 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12984,6 +12984,31 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, ICE->getValueKind()); } + if (auto *GSE = dyn_cast<GenericSelectionExpr>(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<Expr *, 4> 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<UnaryOperator>(E)) { assert(UnOp->getOpcode() == UO_AddrOf && "Can only take the address of an overloaded function"); diff --git a/clang/test/Sema/generic-selection.c b/clang/test/Sema/generic-selection.c index 5c02005d0fa..98299583057 100644 --- a/clang/test/Sema/generic-selection.c +++ b/clang/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); +} |

