Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2018-02-09 04:40:47 +0000
committerNathan Ridge2018-02-12 00:13:28 +0000
commitae8b4e25da919d069db7b595c9fc9741ffa62f86 (patch)
tree21cf2917872b38499f19842b2c41171aa8ef2d4d
parenta8cf65fa75e32249bb753f44a058da024e8af6ee (diff)
downloadorg.eclipse.cdt-ae8b4e25da919d069db7b595c9fc9741ffa62f86.tar.gz
org.eclipse.cdt-ae8b4e25da919d069db7b595c9fc9741ffa62f86.tar.xz
org.eclipse.cdt-ae8b4e25da919d069db7b595c9fc9741ffa62f86.zip
Bug 519091 - Do not bypass the caching mechanism for class member specializations
Direct calls to CPPTemplates.createSpecialization() bypass the caching mechanism, resulting in the violation of invariants such as every binding being represented by a unique (AST-derived) binding object. ICPPClassSpecialization.specializeMember() should be used instead. Change-Id: I10ddb06d087d97cf05c6bed0d9f14a15440b87fe
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java31
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java2
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java17
6 files changed, 68 insertions, 9 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java
index f172faccb84..c5c65d39bfa 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java
@@ -3167,4 +3167,35 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
public void testSpecializationOfAnonymousClass_528456() throws Exception {
checkBindings();
}
+
+ // // empty file
+
+ // namespace std {
+ // template <class E>
+ // struct initializer_list {
+ // const E* array;
+ // int len;
+ // constexpr const E* begin() const { return array; }
+ // constexpr const E* end() const { return array + len; }
+ // };
+ // }
+ // template <typename Enum>
+ // struct QFlags {
+ // int i;
+ // constexpr QFlags(std::initializer_list<Enum> flags)
+ // : i(initializer_list_helper(flags.begin(), flags.end())) {}
+ // constexpr static int initializer_list_helper(const Enum* it, const Enum* end) {
+ // return it == end ? 0 : (int(*it) | initializer_list_helper(it + 1, end));
+ // }
+ // };
+ // enum Option {
+ // ShowMessageBox = 0x02,
+ // Log = 0x04
+ // };
+ // struct MessageFunctionPrivate {
+ // QFlags<Option> Options{ShowMessageBox, Log};
+ // };
+ public void testConstexprInitListConstructor_519091() throws Exception {
+ checkBindings();
+ }
}
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 3ac22c11d96..845a3256fdb 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
@@ -978,6 +978,16 @@ public class CPPTemplates {
return newVariable;
}
+ /**
+ * IMPORTANT: Do NOT call this method directly, at least when (owner instanceof ICPPClassSpecialization).
+ * Use ICPPClassSpecialization.specializeMember(decl) instead.
+ *
+ * This ensures that the caching mechanism for member specializations implemented by
+ * ICPPClassSpecialization.specializeMember() is not bypassed.
+ *
+ * TODO: Implement a caching mechanism for non-class owners, too, and make specializeMember()
+ * a method of ICPPSpecialization itself.
+ */
public static IBinding createSpecialization(ICPPSpecialization owner, IBinding decl) {
IBinding spec = null;
final ICPPTemplateParameterMap tpMap= owner.getTemplateParameterMap();
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java
index cef11e192a3..44c0bc953a9 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java
@@ -264,10 +264,10 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
ICPPFunction[] originalFunctions = fFunctionSet.getBindings();
ICPPFunction[] functions = originalFunctions;
if (owner instanceof ICPPClassSpecialization && owner != originalOwner) {
+ ICPPClassSpecialization ownerClass = (ICPPClassSpecialization) owner;
functions = new ICPPFunction[originalFunctions.length];
for (int i = 0; i < originalFunctions.length; i++) {
- functions[i] = (ICPPFunction) CPPTemplates.createSpecialization((ICPPClassSpecialization) owner,
- originalFunctions[i]);
+ functions[i] = (ICPPFunction) ownerClass.specializeMember(originalFunctions[i]);
}
}
// No need to instantiate the implied object type. An EvalFunctioNSet should only be created
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java
index 6e49cc6b1d0..af5622c8d36 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java
@@ -388,7 +388,7 @@ public class EvalMemberAccess extends CPPDependentEvaluation {
IBinding member = fMember;
IType ownerClass = SemanticUtil.getNestedType(ownerType, ALLCVQ);
if (ownerClass instanceof ICPPClassSpecialization) {
- member = CPPTemplates.createSpecialization((ICPPClassSpecialization) ownerClass, fMember);
+ member = ((ICPPClassSpecialization) ownerClass).specializeMember(fMember);
}
ICPPEvaluation ownerEval = fOwnerEval;
if (ownerEval != null) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java
index 63d40248ec5..dcddf9ac317 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java
@@ -20,8 +20,10 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.CompositeValue;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
@@ -222,8 +224,15 @@ public final class ExecDeclarator implements ICPPExecution {
ICPPVariable declaredVariable = (ICPPVariable) declaredBinding;
newDeclaredBinding = CPPTemplates.createVariableSpecialization(context, declaredVariable);
} else {
- newDeclaredBinding = (ICPPBinding) CPPTemplates.createSpecialization(
- context.getContextSpecialization(), declaredBinding);
+ ICPPSpecialization owner = context.getContextSpecialization();
+ if (owner instanceof ICPPClassSpecialization) {
+ newDeclaredBinding = (ICPPBinding)
+ ((ICPPClassSpecialization) owner).specializeMember(declaredBinding);
+ } else {
+ // TODO: Non-class owners should also have a specializeMember() function which
+ // implements a caching mechanism.
+ newDeclaredBinding = (ICPPBinding) CPPTemplates.createSpecialization(owner, declaredBinding);
+ }
}
ICPPEvaluation newInitializerEval =
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java
index 863fd7b218b..53de3ded8bb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java
@@ -20,10 +20,12 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext;
@@ -167,10 +169,17 @@ public class ExecRangeBasedFor implements ICPPExecution {
// Alternatively, we could lower the range-based for loop into a regular for loop as
// described in the standard (by constructing the corresponding executions and evaluations),
// and the above instantiations will fall out of that automatically.
- ICPPFunction newBegin = begin != null ? (ICPPFunction)CPPTemplates.createSpecialization(
- context.getContextSpecialization(), begin) : null;
- ICPPFunction newEnd = end != null ? (ICPPFunction)CPPTemplates.createSpecialization(
- context.getContextSpecialization(), end) : null;
+ ICPPSpecialization owner = context.getContextSpecialization();
+ ICPPFunction newBegin = null;
+ ICPPFunction newEnd = null;
+ if (owner instanceof ICPPClassSpecialization) {
+ if (begin != null) {
+ newBegin = (ICPPFunction) ((ICPPClassSpecialization) owner).specializeMember(begin);
+ }
+ if (end != null) {
+ newEnd = (ICPPFunction) ((ICPPClassSpecialization) owner).specializeMember(end);
+ }
+ }
ICPPExecution newBodyExec = bodyExec.instantiate(context, maxDepth);
if (newDeclarationExec == declarationExec &&

Back to the top