Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHansruedi Patzen2017-11-21 09:51:19 -0500
committerNathan Ridge2017-11-30 14:56:02 -0500
commita4dcbbaf1519cc06676a6c3355a4c594407efd0a (patch)
tree90627cc48e058f184e11d2062cfd4c5d8c3c3fe2
parent89d45ef7fd160418d0bbb54fb4488748d6db235d (diff)
downloadorg.eclipse.cdt-a4dcbbaf1519cc06676a6c3355a4c594407efd0a.tar.gz
org.eclipse.cdt-a4dcbbaf1519cc06676a6c3355a4c594407efd0a.tar.xz
org.eclipse.cdt-a4dcbbaf1519cc06676a6c3355a4c594407efd0a.zip
Bug 527553: Detect invalid decltype(auto) with a type specifier
The evaluated type of 'decltype(auto)' in combination with const and/or volatile will be a ProblemType since this is not valid code. The patch also contains a checker to give the user a visual feedback. Note: A proposed quick-fix has been removed after a short discussion. Change-Id: I8760ed0ac28e28529ab30516accac9c0413c87d9 Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties4
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/plugin.xml15
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/DecltypeAutoChecker.java45
-rw-r--r--codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/DecltypeAutoCheckerTest.java171
-rw-r--r--codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java2
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java51
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java8
7 files changed, 296 insertions, 0 deletions
diff --git a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
index c5ebf9beed..a478e7851e 100644
--- a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
+++ b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
@@ -127,3 +127,7 @@ problem.description.UnusedStaticFunctionProblem = Finds static functions which c
problem.messagePattern.UnusedStaticFunctionProblem = Unused static function ''{0}''
problem.name.UnusedStaticFunctionProblem = Unused static function
+checker.name.DecltypeAutoChecker = Invalid 'decltype(auto)' specifier checker
+problem.name.DecltypeAutoProblem = Invalid 'decltype(auto)' specifier
+problem.messagePattern.DecltypeAutoProblem = Combining 'decltype(auto)' with other type specifiers is not allowed
+problem.description.DecltypeAutoProblem = This rule will flag 'decltype(auto)' if combined with other type specifiers
diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
index b4b1e025c3..7d44acf36d 100644
--- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml
+++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
@@ -424,5 +424,20 @@
name="Nesting comments">
</problem>
</checker>
+ <checker
+ class="org.eclipse.cdt.codan.internal.checkers.DecltypeAutoChecker"
+ id="org.eclipse.cdt.codan.internal.checkers.DecltypeAutoChecker"
+ name="%checker.name.DecltypeAutoChecker">
+ <problem
+ category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
+ defaultEnabled="true"
+ defaultSeverity="Error"
+ description="%problem.description.DecltypeAutoProblem"
+ id="org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem"
+ markerType="org.eclipse.cdt.codan.core.codanProblem"
+ messagePattern="%problem.messagePattern.DecltypeAutoProblem"
+ name="%problem.name.DecltypeAutoProblem">
+ </problem>
+ </checker>
</extension>
</plugin>
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/DecltypeAutoChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/DecltypeAutoChecker.java
new file mode 100644
index 0000000000..f071bbe217
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/DecltypeAutoChecker.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Institute for Software, HSR Hochschule fuer Technik
+ * Rapperswil, University of applied sciences.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.checkers;
+
+import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
+import org.eclipse.cdt.core.dom.ast.ASTVisitor;
+import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
+
+public class DecltypeAutoChecker extends AbstractIndexAstChecker {
+ public static final String ERR_ID = "org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem"; //$NON-NLS-1$
+
+ @Override
+ public boolean runInEditor() {
+ return true;
+ }
+
+ @Override
+ public void processAst(IASTTranslationUnit ast) {
+ ast.accept(new ASTVisitor() {
+ {
+ shouldVisitDeclSpecifiers = true;
+ }
+
+ @Override
+ public int visit(IASTDeclSpecifier specifier) {
+ if (specifier instanceof ICPPASTSimpleDeclSpecifier) {
+ if (((ICPPASTSimpleDeclSpecifier) specifier).getType() == ICPPASTSimpleDeclSpecifier.t_decltype_auto) {
+ if (specifier.isConst() || specifier.isVolatile()) {
+ reportProblem(ERR_ID, specifier);
+ }
+ }
+ }
+ return PROCESS_CONTINUE;
+ }
+ });
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/DecltypeAutoCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/DecltypeAutoCheckerTest.java
new file mode 100644
index 0000000000..3af9c505b0
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/DecltypeAutoCheckerTest.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Institute for Software, HSR Hochschule fuer Technik
+ * Rapperswil, University of applied sciences.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.internal.checkers;
+
+import org.eclipse.cdt.codan.core.tests.CheckerTestCase;
+import org.eclipse.cdt.codan.internal.checkers.DecltypeAutoChecker;
+
+/**
+ * Test for {@link DecltypeAutoChecker} class
+ */
+public class DecltypeAutoCheckerTest extends CheckerTestCase {
+
+ public static final String ERR_ID = DecltypeAutoChecker.ERR_ID;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ enableProblems(ERR_ID);
+ }
+
+ @Override
+ public boolean isCpp() {
+ return true;
+ }
+
+ // int i { 42 }
+ // decltype(i) k = i;
+ public void testDecltypeExpressionVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // int i { 42 }
+ // decltype(i) volatile k = i;
+ public void testDecltypeExpressionVolatileVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // int i { 42 }
+ // decltype(i) const k = i;
+ public void testDecltypeExpressionConstVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // int i { 42 }
+ // decltype(i) const volatile k = i;
+ public void testDecltypeExpressionCVVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // decltype(auto) i { 42 };
+ public void testDecltypeAutoVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // decltype(auto) const i { 42 };
+ public void testDecltypeAutoConstVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // decltype(auto) volatile i { 42 };
+ public void testDecltypeAutoVolatileVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // decltype(auto) const volatile i { 42 };
+ public void testDecltypeAutoCVVariable() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // void foo() {
+ // decltype(auto) const i { 42 };
+ // }
+ public void testDecltypeAutoConstVariablInsideFunction() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2, ERR_ID);
+ }
+
+ // void foo() {
+ // decltype(auto) volatile i { 42 };
+ // }
+ public void testDecltypeAutoVolatileVariableInsideFunction() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2, ERR_ID);
+ }
+
+ // void foo() {
+ // decltype(auto) const volatile i { 42 };
+ // }
+ public void testDecltypeAutoCVVariableInsideFunction() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2, ERR_ID);
+ }
+
+ // decltype(auto) foo() {
+ // return 42;
+ // }
+ public void testDecltypeAutoReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // decltype(auto) const foo() {
+ // return 42;
+ // }
+ public void testDecltypeAutoConstReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // decltype(auto) volatile foo() {
+ // return 42;
+ // }
+ public void testDecltypeAutoVolatileReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // decltype(auto) const volatile foo() {
+ // return 42;
+ // }
+ public void testDecltypeAutoCVReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // auto foo() -> decltype(auto) {
+ // return 42;
+ // }
+ public void testDecltypeAutoTrailingReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrorsOfKind(ERR_ID);
+ }
+
+ // auto foo() -> decltype(auto) const {
+ // return 42;
+ // }
+ public void testDecltypeAutoConstTrailingReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // auto foo() -> decltype(auto) volatile {
+ // return 42;
+ // }
+ public void testDecltypeAutoVolatileTrailingReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+
+ // auto foo() -> decltype(auto) const volatile {
+ // return 42;
+ // }
+ public void testDecltypeAutoCVTrailingReturnType() throws Exception {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(1, ERR_ID);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java
index 71bf0ca262..5756094745 100644
--- a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java
+++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java
@@ -19,6 +19,7 @@ import org.eclipse.cdt.codan.core.internal.checkers.CatchByReferenceTest;
import org.eclipse.cdt.codan.core.internal.checkers.ClassMembersInitializationCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.CommentCheckerLineTests;
import org.eclipse.cdt.codan.core.internal.checkers.CommentCheckerNestedTests;
+import org.eclipse.cdt.codan.core.internal.checkers.DecltypeAutoCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.FormatStringCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.NonVirtualDestructorCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.ProblemBindingCheckerTest;
@@ -66,6 +67,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTestSuite(CaseBreakCheckerTest.class);
suite.addTestSuite(CatchByReferenceTest.class);
suite.addTestSuite(ClassMembersInitializationCheckerTest.class);
+ suite.addTestSuite(DecltypeAutoCheckerTest.class);
suite.addTestSuite(FormatStringCheckerTest.class);
suite.addTestSuite(NonVirtualDestructorCheckerTest.class);
suite.addTestSuite(ProblemBindingCheckerTest.class);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
index 1d1537171f..dca395e394 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
@@ -12268,6 +12268,9 @@ public class AST2CPPTests extends AST2CPPTestBase {
// decltype(auto) j{42}; // Valid since C++17: decltype(j) is int
// decltype(auto) k = new decltype(auto)(1L); // decltype(j) is long int *
// decltype(auto) l; // Error - missing initializer.
+ // decltype(auto) const m = 42; // Error - decltype(auto) does not allow type specifiers. Bug 527553
+ // decltype(auto) volatile n = 42; // Error - decltype(auto) does not allow type specifiers. Bug 527553
+ // decltype(auto) const volatile o = 42; // Error - decltype(auto) does not allow type specifiers. Bug 527553
public void testDecltypeAutoVariableTypes_482225() throws Exception {
String code = getAboveComment();
BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
@@ -12306,6 +12309,54 @@ public class AST2CPPTests extends AST2CPPTestBase {
ICPPVariable l = bh.assertNonProblem("l;", 1);
IProblemType lType = (IProblemType) l.getType();
assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, lType.getID());
+
+ ICPPVariable m = bh.assertNonProblem("m =", 1);
+ IProblemType mType = (IProblemType) m.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, mType.getID());
+
+ ICPPVariable n = bh.assertNonProblem("n =", 1);
+ IProblemType nType = (IProblemType) n.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, nType.getID());
+
+ ICPPVariable o = bh.assertNonProblem("o =", 1);
+ IProblemType oType = (IProblemType) o.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, oType.getID());
+ }
+
+ // auto foo() -> decltype(auto) const {
+ // return 23.0;
+ // }
+ // auto a = foo();
+ public void testDecltypeAutoTrailingReturnTypeConst_527553() throws Exception {
+ String code = getAboveComment();
+ BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
+ ICPPVariable a = bh.assertNonProblem("a =", 1);
+ IProblemType aType = (IProblemType) a.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE, aType.getID());
+ }
+
+ // auto foo() -> decltype(auto) volatile {
+ // return 23.0;
+ // }
+ // auto a = foo();
+ public void testDecltypeAutoTrailingReturnTypeVolatile_527553() throws Exception {
+ String code = getAboveComment();
+ BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
+ ICPPVariable a = bh.assertNonProblem("a =", 1);
+ IProblemType aType = (IProblemType) a.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE, aType.getID());
+ }
+
+ // auto foo() -> decltype(auto) const {
+ // return 23.0;
+ // }
+ // decltype(auto) a = foo();
+ public void testDecltypeAutoTrailingReturnTypeConstDecltype_527553() throws Exception {
+ String code = getAboveComment();
+ BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
+ ICPPVariable a = bh.assertNonProblem("a =", 1);
+ IProblemType aType = (IProblemType) a.getType();
+ assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, aType.getID());
}
// auto foo() -> decltype(auto) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
index c24d6402b1..4ccbc5f274 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
@@ -2270,6 +2270,10 @@ public class CPPVisitor extends ASTQueries {
// 'decltype(auto)' cannot be combined with * or & the way 'auto' can.
return ProblemType.CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE;
}
+ if (declSpec.isConst() || declSpec.isVolatile()) {
+ // 'decltype(auto)' cannot be combined with any type specifiers. [dcl.type.auto.deduct]
+ return ProblemType.CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE;
+ }
if (autoInitClause instanceof IASTExpression) {
return getDeclType((IASTExpression) autoInitClause);
} else {
@@ -2392,6 +2396,10 @@ public class CPPVisitor extends ASTQueries {
// 'decltype(auto)' cannot be combined with * or & the way 'auto' can.
return ProblemType.CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE;
}
+ if (autoDeclSpec.isConst() || autoDeclSpec.isVolatile()) {
+ // 'decltype(auto)' cannot be combined with any type specifiers. [dcl.type.auto.deduct]
+ return ProblemType.CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE;
+ }
return CPPSemantics.getDeclTypeForEvaluation(returnEval);
} else /* auto */ {
return createAutoType(returnEval, autoDeclSpec, autoDeclarator);

Back to the top