From 9c0d9fec08758435dd7622da729f540fe00ba12a Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 7 May 2017 20:38:59 -0400 Subject: [PATCH] Bug 516290 - Correct computation of decltype(expr) for dependent expressions Change-Id: Iabc49563e85e8649a94a77210eb066253925ea3c --- .../parser/tests/ast2/AST2TemplateTests.java | 16 ++++++++++++ .../parser/cpp/semantics/CPPSemantics.java | 25 +++++++++++++++++++ .../parser/cpp/semantics/CPPTemplates.java | 5 ++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index c7ca12fdcf9..f8147702a18 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -10216,6 +10216,22 @@ public class AST2TemplateTests extends AST2TestBase { parseAndCheckBindings(); } + // struct S { + // int& foo(); + // }; + // + // template + // decltype(S().foo()) bar(); + // + // void waldo(int&); + // + // int main() { + // waldo(bar()); + // } + public void testDependentMemberAccess_516290() throws Exception { + parseAndCheckBindings(); + } + // template // struct A; // diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index e933baee8cf..157fe372339 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -4410,4 +4410,29 @@ public class CPPSemantics { public static boolean isUsingPromiscuousBindingResolution() { return fAllowPromiscuousBindingResolution.get(); } + + /** + * Compute decltype(expr) for an expression represented by an evaluation. + * This is similar to CPPVisitor.getDeclType(IASTExpression), but used in cases where the + * original expression was dependent, so we had to represent it as an evaluation and + * instantiate it. + * + * @param eval the (instantiated) evaluation representing the expression + * @param point + */ + public static IType getDeclTypeForEvaluation(ICPPEvaluation eval, IASTNode point) { + IType expressionType = eval.getType(point); + boolean namedEntity = eval instanceof EvalBinding || eval instanceof EvalMemberAccess; + if (!namedEntity && !(expressionType instanceof ICPPReferenceType)) { + switch (eval.getValueCategory(point)) { + case XVALUE: + return new CPPReferenceType(expressionType, true); + case LVALUE: + return new CPPReferenceType(expressionType, false); + case PRVALUE: + break; + } + } + return expressionType; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 6b48e37cfce..3e5e49aa2d2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -1525,8 +1525,9 @@ public class CPPTemplates { if (type instanceof TypeOfDependentExpression) { ICPPEvaluation eval = ((TypeOfDependentExpression) type).getEvaluation(); ICPPEvaluation instantiated = eval.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); - if (instantiated != eval) - return instantiated.getType(context.getPoint()); + if (instantiated != eval) { + return CPPSemantics.getDeclTypeForEvaluation(instantiated, context.getPoint()); + } } else { IBinding binding= resolveUnknown((ICPPUnknownBinding) type, context); if (binding instanceof IType)