diff options
Diffstat (limited to 'clang')
| -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); +} |

