diff --git a/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/ASTFailedTests.java b/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/ASTFailedTests.java index 6cb6980fc1e..b1ff8608e58 100644 --- a/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/ASTFailedTests.java +++ b/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/ASTFailedTests.java @@ -87,18 +87,6 @@ public class ASTFailedTests extends BaseASTTest assertCodeFailsParse("register int *foo asm (\"a5\");"); } - public void testBug39701A() throws Exception - { - assertCodeFailsParse("extern template int max (int, int);"); - } - public void testBug39701B() throws Exception - { - assertCodeFailsParse("inline template class Foo;"); - } - public void testBug39701C() throws Exception - { - assertCodeFailsParse("static template class Foo;"); - } public void testBug39702() throws Exception { Writer code = new StringWriter(); diff --git a/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/FailedCompleteParseASTTest.java b/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/FailedCompleteParseASTTest.java index b68f3c78cba..c64fd5e90fc 100644 --- a/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/FailedCompleteParseASTTest.java +++ b/core/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/parser/failedTests/FailedCompleteParseASTTest.java @@ -160,17 +160,4 @@ public class FailedCompleteParseASTTest extends CompleteParseBaseTest } - public void testGNUExternalTemplate_bug71603() throws Exception { - try { - parse("template \n class A {}; \n extern template class A; \n"); //$NON-NLS-1$ - fail(); - } catch (ParserException e) { - assertTrue( e.getMessage().equals( "FAILURE" ) ); //$NON-NLS-1$ - } -// Iterator i = parse("template \n class A {}; \n extern template class A; \n").getDeclarations(); -// IASTTemplateDeclaration td = (IASTTemplateDeclaration) i.next(); -// IASTClassSpecifier cs = (IASTClassSpecifier) td.getOwnedDeclaration(); -// IASTTemplateInstantiation ti = (IASTTemplateInstantiation) i.next(); -// assertFalse(i.hasNext()); - } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteParseExtensionsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteParseExtensionsTest.java index cd1348462ca..b41848e8337 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteParseExtensionsTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCCompleteParseExtensionsTest.java @@ -18,9 +18,12 @@ import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ast.ASTPointerOperator; import org.eclipse.cdt.core.parser.ast.ASTUtil; import org.eclipse.cdt.core.parser.ast.IASTASMDefinition; +import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; import org.eclipse.cdt.core.parser.ast.IASTExpression; import org.eclipse.cdt.core.parser.ast.IASTFunction; import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.cdt.core.parser.ast.gcc.IASTGCCExpression; @@ -235,4 +238,13 @@ public class GCCCompleteParseExtensionsTest extends CompleteParseBaseTest { parse( writer.toString(), true, ParserLanguage.C ); } + + public void testGNUExternalTemplate_bug71603() throws Exception { + Iterator i = parse("template \n class A {}; \n extern template class A; \n").getDeclarations(); //$NON-NLS-1$ + IASTTemplateDeclaration td = (IASTTemplateDeclaration) i.next(); + IASTClassSpecifier cs = (IASTClassSpecifier) td.getOwnedDeclaration(); + IASTTemplateInstantiation ti = (IASTTemplateInstantiation) i.next(); + assertFalse(i.hasNext()); + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java index c375d4963d9..c8e4a096229 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/GCCQuickParseExtensionsTest.java @@ -150,4 +150,17 @@ public class GCCQuickParseExtensionsTest extends BaseASTTest { writer.write( "else z = - y;\n" );//$NON-NLS-1$ writer.write( "z; }) zoot;\n" );//$NON-NLS-1$ } + + public void testBug39701A() throws Exception + { + parse("extern template int max (int, int);"); //$NON-NLS-1$ + } + public void testBug39701B() throws Exception + { + parse("inline template class Foo;"); //$NON-NLS-1$ + } + public void testBug39701C() throws Exception + { + parse("static template class Foo;"); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/extension/IParserExtension.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/extension/IParserExtension.java index e8d29102fa1..80d2ef518dd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/extension/IParserExtension.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/extension/IParserExtension.java @@ -76,4 +76,8 @@ public interface IParserExtension { * @return */ public Kind getExpressionKindForStatement(); + + public boolean supportsExtendedTemplateInstantiationSyntax(); + + public boolean isValidModifierForInstantiation( IToken la ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/GCCParserExtension.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/GCCParserExtension.java index 5839218aed7..2360a8b5afb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/GCCParserExtension.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/GCCParserExtension.java @@ -463,4 +463,27 @@ public class GCCParserExtension implements IParserExtension { return IASTGCCExpression.Kind.STATEMENT_EXPRESSION; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.extension.IParserExtension#supportsExtendedTemplateInstantiationSyntax() + */ + public boolean supportsExtendedTemplateInstantiationSyntax() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.extension.IParserExtension#isValidModifierForInstantiation(org.eclipse.cdt.core.parser.IToken) + */ + public boolean isValidModifierForInstantiation(IToken la) { + if( la == null ) return false; + switch( la.getType() ) + { + case IToken.t_static: + case IToken.t_inline: + case IToken.t_extern: + return true; + default: + return false; + } + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java index 8e2a32fd929..1aa5ae37d37 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java @@ -3346,7 +3346,15 @@ public class Parser implements IParserData, IParser consume(IToken.t_template); } else - firstToken = consume(IToken.t_template); + { + if( extension.supportsExtendedTemplateInstantiationSyntax() && extension.isValidModifierForInstantiation(LA(1))) + { + firstToken = consume(); // consume the modifier + consume( IToken.t_template ); + } + else + firstToken = consume(IToken.t_template); + } if (LT(1) != IToken.tLT) { // explicit-instantiation @@ -3721,7 +3729,10 @@ public class Parser implements IParserData, IParser break; } default : - resultDeclaration = simpleDeclarationStrategyUnion(scope, ownerTemplate, overideKind, overideKey); + if( extension.supportsExtendedTemplateInstantiationSyntax() && extension.isValidModifierForInstantiation(LA(1)) && LT(2) == IToken.t_template ) + resultDeclaration = templateDeclaration(scope); + else + resultDeclaration = simpleDeclarationStrategyUnion(scope, ownerTemplate, overideKind, overideKey); } setCompletionValues(scope, kind, KeywordSetKey.DECLARATION ); endDeclaration( resultDeclaration );