summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/Expr.h10
-rw-r--r--clang/lib/Sema/SemaOverload.cpp25
-rw-r--r--clang/test/Sema/generic-selection.c10
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);
+}
OpenPOWER on IntegriCloud