1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Merge remote-tracking branch 'origin/master' into bug_45203

This commit is contained in:
Sergey Prigogin 2013-01-09 15:42:08 -08:00
commit a205a71148
50 changed files with 1127 additions and 622 deletions

View file

@ -221,7 +221,8 @@ public class ScannerInfoConsoleParserUtility extends AbstractGCCBOPConsoleParser
// appending fileName to cwd should yield file path // appending fileName to cwd should yield file path
filePath = cwd.append(fileName); filePath = cwd.append(fileName);
} }
if (!filePath.toString().equalsIgnoreCase(EFSExtensionManager.getDefault().getPathFromURI(file.getLocationURI()))) { IPath fileLocation = new Path(EFSExtensionManager.getDefault().getPathFromURI(file.getLocationURI()));
if (!filePath.toString().equalsIgnoreCase(fileLocation.toString())) {
// must be the cwd is wrong // must be the cwd is wrong
// check if file name starts with ".." // check if file name starts with ".."
if (fileName.startsWith("..")) { //$NON-NLS-1$ if (fileName.startsWith("..")) { //$NON-NLS-1$
@ -238,7 +239,7 @@ public class ScannerInfoConsoleParserUtility extends AbstractGCCBOPConsoleParser
tPath = tPath.removeFirstSegments(1); tPath = tPath.removeFirstSegments(1);
} }
// get the file path from the file // get the file path from the file
filePath = new Path(EFSExtensionManager.getDefault().getPathFromURI(file.getLocationURI())); filePath = fileLocation;
IPath lastFileSegment = filePath.removeFirstSegments(filePath.segmentCount() - tPath.segmentCount()); IPath lastFileSegment = filePath.removeFirstSegments(filePath.segmentCount() - tPath.segmentCount());
if (lastFileSegment.matchingFirstSegments(tPath) == tPath.segmentCount()) { if (lastFileSegment.matchingFirstSegments(tPath) == tPath.segmentCount()) {
cwd = filePath.removeLastSegments(tPath.segmentCount()); cwd = filePath.removeLastSegments(tPath.segmentCount());

View file

@ -18,6 +18,7 @@ import junit.framework.TestSuite;
import org.eclipse.cdt.build.core.scannerconfig.CfgInfoContext; import org.eclipse.cdt.build.core.scannerconfig.CfgInfoContext;
import org.eclipse.cdt.build.core.scannerconfig.ICfgScannerConfigBuilderInfo2Set; import org.eclipse.cdt.build.core.scannerconfig.ICfgScannerConfigBuilderInfo2Set;
import org.eclipse.cdt.build.internal.core.scannerconfig2.CfgScannerConfigProfileManager; import org.eclipse.cdt.build.internal.core.scannerconfig2.CfgScannerConfigProfileManager;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription;
@ -106,6 +107,7 @@ public class CfgScannerConfigProfileManagerTests extends BaseTestCase {
Assert.isTrue("dummyFile".equals(scbi.getBuildOutputFilePath())); Assert.isTrue("dummyFile".equals(scbi.getBuildOutputFilePath()));
// Test restore defaults // Test restore defaults
ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(fProject, false);
scbis.applyInfo(cic, null); scbis.applyInfo(cic, null);
// Save the project description // Save the project description
CoreModel.getDefault().setProjectDescription(fProject, prjDesc); CoreModel.getDefault().setProjectDescription(fProject, prjDesc);

View file

@ -563,7 +563,7 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem
private static List<ILanguageSettingsProvider> getDefaultLanguageSettingsProviders(IConfiguration cfg) { private static List<ILanguageSettingsProvider> getDefaultLanguageSettingsProviders(IConfiguration cfg) {
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>(); List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
String[] ids = cfg.getDefaultLanguageSettingsProviderIds(); String[] ids = cfg != null ? cfg.getDefaultLanguageSettingsProviderIds() : null;
if (ids != null) { if (ids != null) {
for (String id : ids) { for (String id : ids) {
ILanguageSettingsProvider provider = null; ILanguageSettingsProvider provider = null;

View file

@ -15,6 +15,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase; import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
@ -26,6 +29,7 @@ import org.eclipse.cdt.core.settings.model.ICPathEntry;
import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.core.settings.model.ICSettingBase; import org.eclipse.cdt.core.settings.model.ICSettingBase;
import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
@ -73,12 +77,24 @@ public class MBSLanguageSettingsProvider extends AbstractExecutableExtensionBase
if (!new Path(pathStr).isAbsolute()) { if (!new Path(pathStr).isAbsolute()) {
// We need to add project-rooted entry for relative path as MBS counts it this way in some UI // We need to add project-rooted entry for relative path as MBS counts it this way in some UI
// The relative entry below also should be added for indexer to resolve from source file locations // The relative entry below also should be added for indexer to resolve from source file locations
IStringVariableManager mngr = VariablesPlugin.getDefault().getStringVariableManager();
String projectRootedPath = mngr.generateVariableExpression("workspace_loc", rc.getProject().getName()) + Path.SEPARATOR + pathStr; //$NON-NLS-1$ ICdtVariableManager varManager = CCorePlugin.getDefault().getCdtVariableManager();
ICLanguageSettingEntry projectRootedEntry = (ICLanguageSettingEntry) CDataUtil.createEntry(kind, projectRootedPath, projectRootedPath, null, entry.getFlags()); try {
if (! list.contains(projectRootedEntry)) { // Substitute build/environment variables
list.add(projectRootedEntry); String location = varManager.resolveValue(pathStr, "", null, cfgDescription); //$NON-NLS-1$
if (!new Path(location).isAbsolute()) {
IStringVariableManager mngr = VariablesPlugin.getDefault().getStringVariableManager();
String projectRootedPath = mngr.generateVariableExpression("workspace_loc", rc.getProject().getName()) + Path.SEPARATOR + pathStr; //$NON-NLS-1$
ICLanguageSettingEntry projectRootedEntry = (ICLanguageSettingEntry) CDataUtil.createEntry(kind, projectRootedPath, projectRootedPath, null, entry.getFlags());
if (! list.contains(projectRootedEntry)) {
list.add(projectRootedEntry);
}
}
} catch (CdtVariableException e) {
// Swallow exceptions but also log them
ManagedBuilderCorePlugin.log(e);
} }
} }
} }
if (! list.contains(entry)) { if (! list.contains(entry)) {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2010, 2011 Gil Barash * Copyright (c) 2010, 2013 Gil Barash
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -116,7 +116,7 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements IChecke
if (str.toLowerCase().contains(fNoBreakComment.toLowerCase())) if (str.toLowerCase().contains(fNoBreakComment.toLowerCase()))
continue; continue;
} }
reportProblem(curr, prevCase); reportProblem(curr);
} }
} }
} }
@ -159,7 +159,7 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements IChecke
} }
} }
private void reportProblem(IASTStatement curr, IASTStatement prevCase) { private void reportProblem(IASTStatement curr) {
reportProblem(ER_ID, getProblemLocationAtEndOfNode(curr)); reportProblem(ER_ID, getProblemLocationAtEndOfNode(curr));
} }
@ -218,7 +218,7 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements IChecke
super.initPreferences(problem); super.initPreferences(problem);
addPreference(problem, PARAM_NO_BREAK_COMMENT, CheckersMessages.CaseBreakChecker_DefaultNoBreakCommentDescription, addPreference(problem, PARAM_NO_BREAK_COMMENT, CheckersMessages.CaseBreakChecker_DefaultNoBreakCommentDescription,
DEFAULT_NO_BREAK_COMMENT); DEFAULT_NO_BREAK_COMMENT);
addPreference(problem, PARAM_LAST_CASE, CheckersMessages.CaseBreakChecker_LastCaseDescription, Boolean.TRUE); addPreference(problem, PARAM_LAST_CASE, CheckersMessages.CaseBreakChecker_LastCaseDescription, Boolean.FALSE);
addPreference(problem, PARAM_EMPTY_CASE, CheckersMessages.CaseBreakChecker_EmptyCaseDescription, Boolean.FALSE); addPreference(problem, PARAM_EMPTY_CASE, CheckersMessages.CaseBreakChecker_EmptyCaseDescription, Boolean.FALSE);
} }

View file

@ -29,34 +29,22 @@ public class CaseBreakQuickFixTest extends QuickFixTestCase {
// break; // break;
// } // }
//} //}
public void testMiddleCase() throws Exception { public void testSimpleCase() throws Exception {
loadcode(getAboveComment()); loadcode(getAboveComment());
String result = runQuickFixOneFile(); String result = runQuickFixOneFile();
assertContainedIn("break;\tcase 2:", result); assertContainedIn("break;\tcase 2:", result);
} }
//void func() {
// int a;
// switch(a) {
// case 1:
// hello();
// }
//}
public void testLastCase() throws Exception {
loadcode(getAboveComment());
String result = runQuickFixOneFile();
assertContainedIn("break;\t}", result);
}
//void func() { //void func() {
// int a; // int a;
// switch(a) { // switch(a) {
// case 1: { // case 1: {
// hello(); // hello();
// } // }
// default:
// } // }
//} //}
public void testLastCaseComp() throws Exception { public void testCompositeStatementCase() throws Exception {
loadcode(getAboveComment()); loadcode(getAboveComment());
String result = runQuickFixOneFile(); String result = runQuickFixOneFile();
assertContainedIn("hello();\t\tbreak;", result); assertContainedIn("hello();\t\tbreak;", result);

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2009, 2011 Alena Laskavaia * Copyright (c) 2009, 2013 Alena Laskavaia
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -417,9 +417,7 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
IProblem problem = resourceProfile.findProblem(p.getId()); IProblem problem = resourceProfile.findProblem(p.getId());
if (problem == null) if (problem == null)
throw new IllegalArgumentException(p.getId() + " is not registered"); //$NON-NLS-1$ throw new IllegalArgumentException(p.getId() + " is not registered"); //$NON-NLS-1$
if (!problem.isEnabled()) if (problem.isEnabled() && checker instanceof AbstractCheckerWithProblemPreferences) {
return false;
if (checker instanceof AbstractCheckerWithProblemPreferences) {
LaunchModeProblemPreference pref = LaunchModeProblemPreference pref =
((AbstractCheckerWithProblemPreferences) checker).getLaunchModePreference(problem); ((AbstractCheckerWithProblemPreferences) checker).getLaunchModePreference(problem);
if (pref.isRunningInMode(mode)) { if (pref.isRunningInMode(mode)) {

View file

@ -6938,7 +6938,70 @@ public class AST2TemplateTests extends AST2BaseTest {
// static const int value = sizeof(waldo(f)); // static const int value = sizeof(waldo(f));
// }; // };
// typedef identity<Int<S<>::value>>::type reference; // typedef identity<Int<S<>::value>>::type reference;
public void _testDependentExpressions_395243() throws Exception { public void testDependentExpressions_395243a() throws Exception {
parseAndCheckBindings();
}
// typedef char one;
// typedef struct {
// char arr[2];
// } two;
// template <typename T>
// struct has_foo_type {
// template <typename _Up>
// struct wrap_type { };
// template <typename U>
// static one test(wrap_type<typename U::foo_type>*);
// template <typename U>
// static two test(...);
// static const bool value = sizeof(test<T>(0)) == 1;
// };
// template <bool>
// struct traits;
// template <>
// struct traits<true> {
// typedef int bar_type;
// };
// struct S {
// typedef int foo_type;
// };
// traits<has_foo_type<S>::value>::bar_type a;
public void testDependentExpressions_395243b() throws Exception {
parseAndCheckBindings();
}
// template <typename U> U bar(U);
// template <typename T> auto waldo(T t) -> decltype(bar(t));
// struct S {
// void foo() const;
// };
// struct V {
// S arr[5];
// };
// int main() {
// V e;
// auto v = waldo(e);
// for (auto s : v.arr)
// s.foo();
// }
public void testDependentExpressions_395243c() throws Exception {
parseAndCheckBindings();
}
// template <typename> class C {};
// template <typename T> int begin(C<T>);
// template <typename>
// struct A {
// class B {
// void m();
// };
// void test() {
// B* v[5];
// for (auto x : v)
// x->m();
// }
// };
public void testDependentExpressions_395243d() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
} }

View file

@ -7420,4 +7420,9 @@ public class AST2Tests extends AST2BaseTest {
public void testGCCDecltype_397227() throws Exception { public void testGCCDecltype_397227() throws Exception {
parseAndCheckBindings(getAboveComment(), CPP, true); parseAndCheckBindings(getAboveComment(), CPP, true);
} }
// #define macro(R) #R""
public void testNoRawStringInPlainC_397127() throws Exception {
parseAndCheckBindings(getAboveComment(), ParserLanguage.C, true);
}
} }

View file

@ -27,10 +27,12 @@ public class LexerTests extends BaseTestCase {
private static final LexerOptions NO_DOLLAR = new LexerOptions(); private static final LexerOptions NO_DOLLAR = new LexerOptions();
private static final LexerOptions NO_MINMAX = new LexerOptions(); private static final LexerOptions NO_MINMAX = new LexerOptions();
private static final LexerOptions SLASH_PERCENT = new LexerOptions(); private static final LexerOptions SLASH_PERCENT = new LexerOptions();
private static final LexerOptions CPP_OPTIONS = new LexerOptions();
static { static {
NO_DOLLAR.fSupportDollarInIdentifiers= false; NO_DOLLAR.fSupportDollarInIdentifiers= false;
NO_MINMAX.fSupportMinAndMax= false; NO_MINMAX.fSupportMinAndMax= false;
SLASH_PERCENT.fSupportSlashPercentComments= true; SLASH_PERCENT.fSupportSlashPercentComments= true;
CPP_OPTIONS.fSupportRawStringLiterals= true;
} }
static String TRIGRAPH_REPLACES_CHARS= "#^[]|{}~\\"; static String TRIGRAPH_REPLACES_CHARS= "#^[]|{}~\\";
@ -41,7 +43,7 @@ public class LexerTests extends BaseTestCase {
} }
private Lexer fLexer; private Lexer fLexer;
private TestLexerLog fLog= new TestLexerLog(); private final TestLexerLog fLog= new TestLexerLog();
private int fLastEndOffset; private int fLastEndOffset;
public LexerTests() { public LexerTests() {
@ -576,51 +578,51 @@ public class LexerTests extends BaseTestCase {
public void testRawStringLiteral() throws Exception { public void testRawStringLiteral() throws Exception {
String lit= "abc0123\\\"'.:; \\\\ \n\"("; String lit= "abc0123\\\"'.:; \\\\ \n\"(";
init("R\"(" + lit + ")\""); init("R\"(" + lit + ")\"", CPP_OPTIONS);
rstr("", lit); rstr("", lit);
eof(); eof();
init("LR\"(" + lit + ")\""); init("LR\"(" + lit + ")\"", CPP_OPTIONS);
wrstr("", lit); wrstr("", lit);
eof(); eof();
init("u8R\"(" + lit + ")\""); init("u8R\"(" + lit + ")\"", CPP_OPTIONS);
utf8rstr("", lit); utf8rstr("", lit);
eof(); eof();
init("uR\"(" + lit + ")\""); init("uR\"(" + lit + ")\"", CPP_OPTIONS);
utf16rstr("", lit); utf16rstr("", lit);
eof(); eof();
init("UR\"(" + lit + ")\""); init("UR\"(" + lit + ")\"", CPP_OPTIONS);
utf32rstr("", lit); utf32rstr("", lit);
eof(); eof();
init("R\"ut"); init("R\"ut", CPP_OPTIONS);
problem(IProblem.SCANNER_UNBOUNDED_STRING, "R\"ut"); problem(IProblem.SCANNER_UNBOUNDED_STRING, "R\"ut");
token(IToken.tSTRING, "R\"ut"); token(IToken.tSTRING, "R\"ut");
eof(); eof();
init("LR\"(ut"); init("LR\"(ut", CPP_OPTIONS);
problem(IProblem.SCANNER_UNBOUNDED_STRING, "LR\"(ut"); problem(IProblem.SCANNER_UNBOUNDED_STRING, "LR\"(ut");
token(IToken.tLSTRING, "LR\"(ut"); token(IToken.tLSTRING, "LR\"(ut");
eof(); eof();
init("uR\"p()"); init("uR\"p()", CPP_OPTIONS);
problem(IProblem.SCANNER_UNBOUNDED_STRING, "uR\"p()"); problem(IProblem.SCANNER_UNBOUNDED_STRING, "uR\"p()");
token(IToken.tUTF16STRING, "uR\"p()"); token(IToken.tUTF16STRING, "uR\"p()");
eof(); eof();
init("UR\"(ut"); init("UR\"(ut", CPP_OPTIONS);
problem(IProblem.SCANNER_UNBOUNDED_STRING, "UR\"(ut"); problem(IProblem.SCANNER_UNBOUNDED_STRING, "UR\"(ut");
token(IToken.tUTF32STRING, "UR\"(ut"); token(IToken.tUTF32STRING, "UR\"(ut");
eof(); eof();
init("R\"+=(Text)=+\"Text)+=\""); init("R\"+=(Text)=+\"Text)+=\"", CPP_OPTIONS);
rstr("+=", "Text)=+\"Text"); rstr("+=", "Text)=+\"Text");
eof(); eof();
init("UR uR LR u8R U8R\"\""); init("UR uR LR u8R U8R\"\"", CPP_OPTIONS);
id("UR"); ws(); id("UR"); ws();
id("uR"); ws(); id("uR"); ws();
id("LR"); ws(); id("LR"); ws();
@ -630,7 +632,7 @@ public class LexerTests extends BaseTestCase {
} }
public void testRawStringLiteralInInactiveCode() throws Exception { public void testRawStringLiteralInInactiveCode() throws Exception {
init("start\n" + "inactive: Rbla\n" + "#end"); init("start\n" + "inactive: Rbla\n" + "#end", CPP_OPTIONS);
id("start"); id("start");
nextDirective(); nextDirective();
token(IToken.tPOUND); token(IToken.tPOUND);
@ -638,7 +640,7 @@ public class LexerTests extends BaseTestCase {
eof(); eof();
// raw string containing a directive // raw string containing a directive
init("start\n" + "inactive: uR\"(\n#endif\n)\"\n" + "#end"); init("start\n" + "inactive: uR\"(\n#endif\n)\"\n" + "#end", CPP_OPTIONS);
id("start"); id("start");
nextDirective(); nextDirective();
token(IToken.tPOUND); token(IToken.tPOUND);

View file

@ -29,8 +29,8 @@ public abstract class AbstractScannerExtensionConfiguration implements IScannerE
private CharArrayIntMap fAddPreprocessorKeywords; private CharArrayIntMap fAddPreprocessorKeywords;
protected static class MacroDefinition implements IMacro { protected static class MacroDefinition implements IMacro {
private char[] fSignature; private final char[] fSignature;
private char[] fExpansion; private final char[] fExpansion;
MacroDefinition(char[] signature, char[] expansion) { MacroDefinition(char[] signature, char[] expansion) {
fSignature= signature; fSignature= signature;
@ -103,6 +103,14 @@ public abstract class AbstractScannerExtensionConfiguration implements IScannerE
return false; return false;
} }
/**
* @since 5.5
*/
@Override
public boolean supportRawStringLiterals() {
return false;
}
@Override @Override
public CharArrayIntMap getAdditionalPreprocessorKeywords() { public CharArrayIntMap getAdditionalPreprocessorKeywords() {
return fAddPreprocessorKeywords; return fAddPreprocessorKeywords;

View file

@ -109,4 +109,10 @@ public interface IScannerExtensionConfiguration {
* @see "http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/language_ref/unicode_standard.html" * @see "http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/language_ref/unicode_standard.html"
*/ */
public boolean supportUTFLiterals(); public boolean supportUTFLiterals();
/**
* Support for C++ raw string literals.
* @since 5.5
*/
public boolean supportRawStringLiterals();
} }

View file

@ -113,4 +113,12 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
public boolean supportMinAndMaxOperators() { public boolean supportMinAndMaxOperators() {
return true; return true;
} }
/**
* @since 5.5
*/
@Override
public boolean supportRawStringLiterals() {
return true;
}
} }

View file

@ -8,12 +8,11 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
@ -30,19 +29,32 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFuncti
private static final ICPPFunctionType FUNCTION_TYPE= private static final ICPPFunctionType FUNCTION_TYPE=
new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY); new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY);
public static ICPPFunction createForSample(IFunction sample) throws DOMException { /**
if (sample instanceof ICPPConstructor) * Creates a CPPDeferredFunction given a set of overloaded functions
return new CPPUnknownConstructor(((ICPPConstructor) sample).getClassOwner()); * (some of which may be templates) that the function might resolve to.
* At least one candidate must be provided.
* @param candidates a set of overloaded functions, some of which may be templates
* @return the constructed CPPDeferredFunction
*/
public static ICPPFunction createForCandidates(ICPPFunction... candidates) {
if (candidates[0] instanceof ICPPConstructor)
return new CPPUnknownConstructor(((ICPPConstructor) candidates[0]).getClassOwner(), candidates);
final IBinding owner = sample.getOwner(); final IBinding owner = candidates[0].getOwner();
return new CPPDeferredFunction(owner, sample.getNameCharArray()); return new CPPDeferredFunction(owner, candidates[0].getNameCharArray(), candidates);
} }
private final IBinding fOwner; private final IBinding fOwner;
private final ICPPFunction[] fCandidates;
public CPPDeferredFunction(IBinding owner, char[] name) { public CPPDeferredFunction(IBinding owner, char[] name, ICPPFunction[] candidates) {
super(name); super(name);
fOwner= owner; fOwner= owner;
fCandidates = candidates;
}
public ICPPFunction[] getCandidates() {
return fCandidates;
} }
@Override @Override

View file

@ -8,11 +8,13 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
/** /**
* Represents a reference to a constructor (instance), which cannot be resolved because * Represents a reference to a constructor (instance), which cannot be resolved because
@ -21,7 +23,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
public class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPConstructor { public class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPConstructor {
public CPPUnknownConstructor(ICPPClassType owner) { public CPPUnknownConstructor(ICPPClassType owner) {
super(owner, owner.getNameCharArray()); super(owner, owner.getNameCharArray(), null);
}
public CPPUnknownConstructor(ICPPClassType owner, ICPPFunction[] candidates) {
super(owner, owner.getNameCharArray(), candidates);
} }
@Override @Override

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2012 IBM Corporation and others. * Copyright (c) 2002, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -2057,7 +2057,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
List<ICPPASTTemplateParameter> parms= outerTemplateParameterList(); List<ICPPASTTemplateParameter> parms= outerTemplateParameterList();
consume(IToken.tGT, IToken.tGT_in_SHIFTR); if (LT(1) != IToken.tEOC) {
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
}
IASTDeclaration d = declaration(option); IASTDeclaration d = declaration(option);
ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d); ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d);
setRange(templateDecl, offset, calculateEndOffset(d)); setRange(templateDecl, offset, calculateEndOffset(d));

View file

@ -240,7 +240,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
protected static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args, protected static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args,
ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, IASTNode point) { ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, IASTNode point) {
try { try {
return CPPTemplates.instantiateArguments(args, tpMap, packOffset, within, point); return CPPTemplates.instantiateArguments(args, tpMap, packOffset, within, point, false);
} catch (DOMException e) { } catch (DOMException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
} }

View file

@ -92,7 +92,7 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding {
public void setToUnknown() { public void setToUnknown() {
if (fName != null) { if (fName != null) {
fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray())); fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray(), fBindings));
} }
} }
} }

View file

@ -13,6 +13,7 @@
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Mike Kucera (IBM) * Mike Kucera (IBM)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -451,7 +452,7 @@ public class CPPSemantics {
final ASTNodeProperty namePropertyInParent = name.getPropertyInParent(); final ASTNodeProperty namePropertyInParent = name.getPropertyInParent();
if (binding == null && data.skippedScope != null) { if (binding == null && data.skippedScope != null) {
if (data.hasFunctionArguments()) { if (data.hasFunctionArguments()) {
binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID()); binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID(), null);
} else { } else {
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) { if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID()); binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID());
@ -2395,7 +2396,7 @@ public class CPPSemantics {
if (viableCount == 1) if (viableCount == 1)
return fns[0]; return fns[0];
setTargetedFunctionsToUnknown(argTypes); setTargetedFunctionsToUnknown(argTypes);
return CPPDeferredFunction.createForSample(fns[0]); return CPPDeferredFunction.createForCandidates(fns);
} }
IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good
@ -2403,7 +2404,7 @@ public class CPPSemantics {
// Loop over all functions // Loop over all functions
List<FunctionCost> potentialCosts= null; List<FunctionCost> potentialCosts= null;
IFunction unknownFunction= null; ICPPFunction unknownFunction= null;
final CPPASTTranslationUnit tu = data.getTranslationUnit(); final CPPASTTranslationUnit tu = data.getTranslationUnit();
for (ICPPFunction fn : fns) { for (ICPPFunction fn : fns) {
if (fn == null) if (fn == null)
@ -2455,7 +2456,7 @@ public class CPPSemantics {
return null; return null;
setTargetedFunctionsToUnknown(argTypes); setTargetedFunctionsToUnknown(argTypes);
return CPPDeferredFunction.createForSample(unknownFunction); return CPPDeferredFunction.createForCandidates(fns);
} }
if (ambiguousFunctions != null) { if (ambiguousFunctions != null) {

View file

@ -11,6 +11,7 @@
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -163,7 +164,6 @@ public class CPPTemplates {
static final int PACK_SIZE_DEFER = -1; static final int PACK_SIZE_DEFER = -1;
static final int PACK_SIZE_FAIL = -2; static final int PACK_SIZE_FAIL = -2;
static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE; static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
private static final ICPPFunction[] NO_FUNCTIONS = {};
static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE } static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE }
/** /**
@ -789,7 +789,7 @@ public class CPPTemplates {
ICPPClassTemplate template= pspec.getPrimaryClassTemplate(); ICPPClassTemplate template= pspec.getPrimaryClassTemplate();
ICPPTemplateArgument[] args = pspec.getTemplateArguments(); ICPPTemplateArgument[] args = pspec.getTemplateArguments();
template= (ICPPClassTemplate) owner.specializeMember(template, point); template= (ICPPClassTemplate) owner.specializeMember(template, point);
args= instantiateArguments(args, tpMap, -1, within, point); args= instantiateArguments(args, tpMap, -1, within, point, false);
spec= new CPPClassTemplatePartialSpecializationSpecialization(pspec, tpMap, template, args); spec= new CPPClassTemplatePartialSpecializationSpecialization(pspec, tpMap, template, args);
} catch (DOMException e) { } catch (DOMException e) {
} }
@ -1047,10 +1047,15 @@ public class CPPTemplates {
} }
/** /**
* Instantiates arguments contained in an array. * Instantiates arguments contained in an array. Instantiated arguments are checked for
* validity. If the {@code strict} parameter is {@code true}, the method returns {@code null} if
* any of the instantiated arguments are invalid. If the {@code strict} parameter is
* {@code false}, any invalid instantiated arguments are replaced by the corresponding original
* arguments.
*/ */
public static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args, public static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args,
ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, IASTNode point) ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within,
IASTNode point, boolean strict)
throws DOMException { throws DOMException {
// Don't create a new array until it's really needed. // Don't create a new array until it's really needed.
ICPPTemplateArgument[] result = args; ICPPTemplateArgument[] result = args;
@ -1066,11 +1071,19 @@ public class CPPTemplates {
} else if (packSize == PACK_SIZE_DEFER) { } else if (packSize == PACK_SIZE_DEFER) {
newArg= origArg; newArg= origArg;
} else { } else {
final int shift = packSize - 1; int shift = packSize - 1;
ICPPTemplateArgument[] newResult= new ICPPTemplateArgument[args.length + resultShift + shift]; ICPPTemplateArgument[] newResult= new ICPPTemplateArgument[args.length + resultShift + shift];
System.arraycopy(result, 0, newResult, 0, i + resultShift); System.arraycopy(result, 0, newResult, 0, i + resultShift);
for (int j= 0; j < packSize; j++) { for (int j= 0; j < packSize; j++) {
newResult[i + resultShift + j]= instantiateArgument(origArg, tpMap, j, within, point); newArg = instantiateArgument(origArg, tpMap, j, within, point);
if (!isValidArgument(newArg)) {
if (strict)
return null;
newResult = result;
shift = 0;
break;
}
newResult[i + resultShift + j]= newArg;
} }
result= newResult; result= newResult;
resultShift += shift; resultShift += shift;
@ -1078,7 +1091,13 @@ public class CPPTemplates {
} }
} else { } else {
newArg = instantiateArgument(origArg, tpMap, packOffset, within, point); newArg = instantiateArgument(origArg, tpMap, packOffset, within, point);
if (!isValidArgument(newArg)) {
if (strict)
return null;
newArg = origArg;
}
} }
if (result != args) { if (result != args) {
result[i + resultShift]= newArg; result[i + resultShift]= newArg;
} else if (newArg != origArg) { } else if (newArg != origArg) {
@ -1122,12 +1141,15 @@ public class CPPTemplates {
for (Integer key : positions) { for (Integer key : positions) {
ICPPTemplateArgument arg = orig.getArgument(key); ICPPTemplateArgument arg = orig.getArgument(key);
if (arg != null) { if (arg != null) {
newMap.put(key, instantiateArgument(arg, tpMap, packOffset, within, point)); ICPPTemplateArgument newArg = instantiateArgument(arg, tpMap, packOffset, within, point);
if (!isValidArgument(newArg))
newArg = arg;
newMap.put(key, newArg);
} else { } else {
ICPPTemplateArgument[] args = orig.getPackExpansion(key); ICPPTemplateArgument[] args = orig.getPackExpansion(key);
if (args != null) { if (args != null) {
try { try {
newMap.put(key, instantiateArguments(args, tpMap, packOffset, within, point)); newMap.put(key, instantiateArguments(args, tpMap, packOffset, within, point, false));
} catch (DOMException e) { } catch (DOMException e) {
newMap.put(key, args); newMap.put(key, args);
} }
@ -1211,7 +1233,7 @@ public class CPPTemplates {
final IBinding origClass = classInstance.getSpecializedBinding(); final IBinding origClass = classInstance.getSpecializedBinding();
if (origClass instanceof ICPPClassType) { if (origClass instanceof ICPPClassType) {
ICPPTemplateArgument[] args = classInstance.getTemplateArguments(); ICPPTemplateArgument[] args = classInstance.getTemplateArguments();
ICPPTemplateArgument[] newArgs = instantiateArguments(args, tpMap, packOffset, within, point); ICPPTemplateArgument[] newArgs = instantiateArguments(args, tpMap, packOffset, within, point, false);
if (newArgs != args) { if (newArgs != args) {
CPPTemplateParameterMap tparMap = instantiateArgumentMap(classInstance.getTemplateParameterMap(), tpMap, packOffset, within, point); CPPTemplateParameterMap tparMap = instantiateArgumentMap(classInstance.getTemplateParameterMap(), tpMap, packOffset, within, point);
return new CPPClassInstance((ICPPClassType) origClass, classInstance.getOwner(), tparMap, args); return new CPPClassInstance((ICPPClassType) origClass, classInstance.getOwner(), tparMap, args);
@ -1728,18 +1750,12 @@ public class CPPTemplates {
requireTemplate= false; requireTemplate= false;
if (func instanceof ICPPFunctionTemplate) { if (func instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; if (containsDependentType(fnArgs))
try { return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)};
if (containsDependentType(fnArgs))
return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; if (requireTemplate && hasDependentArgument(tmplArgs))
return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)};
if (requireTemplate) {
if (hasDependentArgument(tmplArgs))
return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)};
}
} catch (DOMException e) {
return NO_FUNCTIONS;
}
haveTemplate= true; haveTemplate= true;
break; break;
} }
@ -1805,15 +1821,11 @@ public class CPPTemplates {
// Extract template arguments and parameter types. // Extract template arguments and parameter types.
if (!checkedForDependentType) { if (!checkedForDependentType) {
try { if (isDependentType(conversionType)) {
if (isDependentType(conversionType)) { inst= CPPDeferredFunction.createForCandidates(functions);
inst= CPPDeferredFunction.createForSample(template); done= true;
done= true;
}
checkedForDependentType= true;
} catch (DOMException e) {
return functions;
} }
checkedForDependentType= true;
} }
CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); CPPTemplateParameterMap map= new CPPTemplateParameterMap(1);
try { try {
@ -1871,7 +1883,7 @@ public class CPPTemplates {
ICPPTemplateArgument[] args, IASTNode point) { ICPPTemplateArgument[] args, IASTNode point) {
try { try {
if (target != null && isDependentType(target)) { if (target != null && isDependentType(target)) {
return CPPDeferredFunction.createForSample(template); return CPPDeferredFunction.createForCandidates(template);
} }
if (template instanceof ICPPConstructor || args == null) if (template instanceof ICPPConstructor || args == null)
@ -2061,12 +2073,7 @@ public class CPPTemplates {
private static boolean checkInstantiationOfArguments(ICPPTemplateArgument[] args, private static boolean checkInstantiationOfArguments(ICPPTemplateArgument[] args,
CPPTemplateParameterMap tpMap, IASTNode point) throws DOMException { CPPTemplateParameterMap tpMap, IASTNode point) throws DOMException {
args = instantiateArguments(args, tpMap, -1, null, point); return instantiateArguments(args, tpMap, -1, null, point, true) != null;
for (ICPPTemplateArgument arg : args) {
if (!isValidArgument(arg))
return false;
}
return true;
} }
/** /**
@ -2124,7 +2131,7 @@ public class CPPTemplates {
args[i]= arg; args[i]= arg;
transferMap.put(param, arg); transferMap.put(param, arg);
} }
final ICPPTemplateArgument[] transferredArgs1 = instantiateArguments(targs1, transferMap, -1, null, point); final ICPPTemplateArgument[] transferredArgs1 = instantiateArguments(targs1, transferMap, -1, null, point, false);
// Deduce arguments for specialization 2 // Deduce arguments for specialization 2
final CPPTemplateParameterMap deductionMap= new CPPTemplateParameterMap(2); final CPPTemplateParameterMap deductionMap= new CPPTemplateParameterMap(2);
@ -2468,7 +2475,7 @@ public class CPPTemplates {
if (unknown instanceof ICPPUnknownMemberClassInstance) { if (unknown instanceof ICPPUnknownMemberClassInstance) {
ICPPUnknownMemberClassInstance ucli= (ICPPUnknownMemberClassInstance) unknown; ICPPUnknownMemberClassInstance ucli= (ICPPUnknownMemberClassInstance) unknown;
ICPPTemplateArgument[] args0 = ucli.getArguments(); ICPPTemplateArgument[] args0 = ucli.getArguments();
ICPPTemplateArgument[] args1 = instantiateArguments(args0, tpMap, packOffset, within, point); ICPPTemplateArgument[] args1 = instantiateArguments(args0, tpMap, packOffset, within, point, false);
if (args0 != args1 || !ot1.isSameType(ot0)) { if (args0 != args1 || !ot1.isSameType(ot0)) {
args1= SemanticUtil.getSimplifiedArguments(args1); args1= SemanticUtil.getSimplifiedArguments(args1);
result= new CPPUnknownClassInstance(ot1, ucli.getNameCharArray(), args1); result= new CPPUnknownClassInstance(ot1, ucli.getNameCharArray(), args1);
@ -2486,7 +2493,7 @@ public class CPPTemplates {
result= CPPSemantics.resolveUnknownName(s, unknown, point); result= CPPSemantics.resolveUnknownName(s, unknown, point);
if (unknown instanceof ICPPUnknownMemberClassInstance && result instanceof ICPPTemplateDefinition) { if (unknown instanceof ICPPUnknownMemberClassInstance && result instanceof ICPPTemplateDefinition) {
ICPPTemplateArgument[] args1 = instantiateArguments( ICPPTemplateArgument[] args1 = instantiateArguments(
((ICPPUnknownMemberClassInstance) unknown).getArguments(), tpMap, packOffset, within, point); ((ICPPUnknownMemberClassInstance) unknown).getArguments(), tpMap, packOffset, within, point, false);
if (result instanceof ICPPClassTemplate) { if (result instanceof ICPPClassTemplate) {
result = instantiate((ICPPClassTemplate) result, args1, point); result = instantiate((ICPPClassTemplate) result, args1, point);
} }
@ -2505,7 +2512,7 @@ public class CPPTemplates {
ICPPTemplateArgument[] arguments = dci.getTemplateArguments(); ICPPTemplateArgument[] arguments = dci.getTemplateArguments();
ICPPTemplateArgument[] newArgs; ICPPTemplateArgument[] newArgs;
try { try {
newArgs = instantiateArguments(arguments, tpMap, packOffset, within, point); newArgs = instantiateArguments(arguments, tpMap, packOffset, within, point, false);
} catch (DOMException e) { } catch (DOMException e) {
return e.getProblem(); return e.getProblem();
} }

View file

@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -2017,11 +2018,13 @@ public class CPPVisitor extends ASTQueries {
IBinding b= implicits[0].getBinding(); IBinding b= implicits[0].getBinding();
CPPASTName name= new CPPASTName(); CPPASTName name= new CPPASTName();
name.setBinding(b); name.setBinding(b);
IASTInitializerClause[] beginCallArguments = new IASTInitializerClause[] { forInit.copy() };
if (b instanceof ICPPMethod && forInit instanceof IASTExpression) { if (b instanceof ICPPMethod && forInit instanceof IASTExpression) {
beginExpr= new CPPASTFunctionCallExpression( beginExpr= new CPPASTFunctionCallExpression(
new CPPASTFieldReference(name, (IASTExpression) forInit.copy()), NO_ARGS); new CPPASTFieldReference(name, (IASTExpression) forInit.copy()),
beginCallArguments);
} else { } else {
beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), NO_ARGS); beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), beginCallArguments);
} }
} else { } else {
return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE); return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE);

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -362,6 +363,13 @@ public class EvalBinding extends CPPEvaluation {
binding = CPPTemplates.createSpecialization((ICPPClassSpecialization) owner, binding = CPPTemplates.createSpecialization((ICPPClassSpecialization) owner,
binding, point); binding, point);
} }
} else if (binding instanceof ICPPParameter) {
ICPPParameter parameter = (ICPPParameter) binding;
IType originalType = parameter.getType();
IType type = CPPTemplates.instantiateType(originalType, tpMap, packOffset, within, point);
if (originalType != type) {
return new EvalFixed(type, ValueCategory.LVALUE, Value.create(this));
}
} }
if (binding == fBinding) if (binding == fBinding)
return this; return this;

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -23,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@ -145,12 +147,16 @@ public class EvalFunctionSet extends CPPEvaluation {
ICPPClassSpecialization within, int maxdepth, IASTNode point) { ICPPClassSpecialization within, int maxdepth, IASTNode point) {
ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments(); ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments();
ICPPTemplateArgument[] arguments = originalArguments; ICPPTemplateArgument[] arguments = originalArguments;
arguments = instantiateArguments(originalArguments, tpMap, packOffset, within, point); if (originalArguments != null)
arguments = instantiateArguments(originalArguments, tpMap, packOffset, within, point);
IBinding originalOwner = fFunctionSet.getOwner(); IBinding originalOwner = fFunctionSet.getOwner();
IBinding owner = originalOwner; IBinding owner = originalOwner;
if (originalOwner instanceof ICPPUnknownBinding) { if (owner instanceof ICPPUnknownBinding) {
owner = resolveUnknown((ICPPUnknownBinding) owner, tpMap, packOffset, within, point); owner = resolveUnknown((ICPPUnknownBinding) owner, tpMap, packOffset, within, point);
} else if (owner instanceof ICPPClassTemplate) {
owner = resolveUnknown(CPPTemplates.createDeferredInstance((ICPPClassTemplate) owner),
tpMap, packOffset, within, point);
} else if (owner instanceof IType) { } else if (owner instanceof IType) {
IType type = CPPTemplates.instantiateType((IType) owner, tpMap, packOffset, within, point); IType type = CPPTemplates.instantiateType((IType) owner, tpMap, packOffset, within, point);
if (type instanceof IBinding) if (type instanceof IBinding)

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -48,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -184,15 +186,6 @@ public class EvalID extends CPPEvaluation {
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr)); return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr));
} }
if (binding instanceof ICPPUnknownBinding) { if (binding instanceof ICPPUnknownBinding) {
IBinding owner = binding.getOwner();
if (owner instanceof IProblemBinding)
return EvalFixed.INCOMPLETE;
ICPPEvaluation fieldOwner= null;
IType fieldOwnerType= withinNonStaticMethod(expr);
if (fieldOwnerType != null) {
fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, Value.UNKNOWN);
}
ICPPTemplateArgument[] templateArgs = null; ICPPTemplateArgument[] templateArgs = null;
final IASTName lastName = name.getLastName(); final IASTName lastName = name.getLastName();
if (lastName instanceof ICPPASTTemplateId) { if (lastName instanceof ICPPASTTemplateId) {
@ -202,6 +195,25 @@ public class EvalID extends CPPEvaluation {
return EvalFixed.INCOMPLETE; return EvalFixed.INCOMPLETE;
} }
} }
if (binding instanceof CPPDeferredFunction) {
CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding;
if (deferredFunction.getCandidates() != null) {
CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, null);
return new EvalFunctionSet(functionSet, isAddressOf(expr));
}
}
IBinding owner = binding.getOwner();
if (owner instanceof IProblemBinding)
return EvalFixed.INCOMPLETE;
ICPPEvaluation fieldOwner= null;
IType fieldOwnerType= withinNonStaticMethod(expr);
if (fieldOwnerType != null) {
fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, Value.UNKNOWN);
}
return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr), return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr),
name instanceof ICPPASTQualifiedName, templateArgs); name instanceof ICPPASTQualifiedName, templateArgs);
} }

View file

@ -290,6 +290,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators(); fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators();
fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments(); fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments();
fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals(); fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals();
fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals();
fLocationMap= new LocationMap(fLexOptions); fLocationMap= new LocationMap(fLexOptions);
fKeywords= new CharArrayIntMap(40, -1); fKeywords= new CharArrayIntMap(40, -1);
fPPKeywords= new CharArrayIntMap(40, -1); fPPKeywords= new CharArrayIntMap(40, -1);

View file

@ -54,6 +54,7 @@ final public class Lexer implements ITokenSequence {
public boolean fCreateImageLocations= true; public boolean fCreateImageLocations= true;
public boolean fSupportSlashPercentComments= false; public boolean fSupportSlashPercentComments= false;
public boolean fSupportUTFLiterals= true; public boolean fSupportUTFLiterals= true;
public boolean fSupportRawStringLiterals= false;
@Override @Override
public Object clone() { public Object clone() {
@ -73,7 +74,7 @@ final public class Lexer implements ITokenSequence {
// the input to the lexer // the input to the lexer
private final AbstractCharArray fInput; private final AbstractCharArray fInput;
private int fStart; private final int fStart;
private int fLimit; private int fLimit;
// after phase 3 (newline, trigraph, line-splice) // after phase 3 (newline, trigraph, line-splice)
@ -267,12 +268,14 @@ final public class Lexer implements ITokenSequence {
case 'L': case 'L':
switch(d) { switch(d) {
case 'R': case 'R':
markPhase3(); if (fOptions.fSupportRawStringLiterals) {
if (nextCharPhase3() == '"') { markPhase3();
nextCharPhase3(); if (nextCharPhase3() == '"') {
return rawStringLiteral(start, 3, IToken.tLSTRING); nextCharPhase3();
return rawStringLiteral(start, 3, IToken.tLSTRING);
}
restorePhase3();
} }
restorePhase3();
break; break;
case '"': case '"':
nextCharPhase3(); nextCharPhase3();
@ -288,12 +291,14 @@ final public class Lexer implements ITokenSequence {
if (fOptions.fSupportUTFLiterals) { if (fOptions.fSupportUTFLiterals) {
switch(d) { switch(d) {
case 'R': case 'R':
markPhase3(); if (fOptions.fSupportRawStringLiterals) {
if (nextCharPhase3() == '"') { markPhase3();
nextCharPhase3(); if (nextCharPhase3() == '"') {
return rawStringLiteral(start, 3, c == 'u' ? IToken.tUTF16STRING : IToken.tUTF32STRING); nextCharPhase3();
return rawStringLiteral(start, 3, c == 'u' ? IToken.tUTF16STRING : IToken.tUTF32STRING);
}
restorePhase3();
} }
restorePhase3();
break; break;
case '"': case '"':
nextCharPhase3(); nextCharPhase3();
@ -306,7 +311,7 @@ final public class Lexer implements ITokenSequence {
markPhase3(); markPhase3();
switch (nextCharPhase3()) { switch (nextCharPhase3()) {
case 'R': case 'R':
if (nextCharPhase3() == '"') { if (fOptions.fSupportRawStringLiterals && nextCharPhase3() == '"') {
nextCharPhase3(); nextCharPhase3();
return rawStringLiteral(start, 4, IToken.tSTRING); return rawStringLiteral(start, 4, IToken.tSTRING);
} }
@ -323,7 +328,7 @@ final public class Lexer implements ITokenSequence {
return identifier(start, 1); return identifier(start, 1);
case 'R': case 'R':
if (d == '"') { if (fOptions.fSupportRawStringLiterals && d == '"') {
nextCharPhase3(); nextCharPhase3();
return rawStringLiteral(start, 2, IToken.tSTRING); return rawStringLiteral(start, 2, IToken.tSTRING);
} }

View file

@ -7,7 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,22 +45,22 @@ public class MacroDefinitionParser {
*/ */
static class TokenParameterReference extends TokenWithImage { static class TokenParameterReference extends TokenWithImage {
private final int fIndex; private final int fIndex;
public TokenParameterReference(int type, int idx, Object source, int offset, int endOffset, char[] name) { public TokenParameterReference(int type, int idx, Object source, int offset, int endOffset, char[] name) {
super(type, source, offset, endOffset, name); super(type, source, offset, endOffset, name);
fIndex= idx; fIndex= idx;
} }
public int getIndex() { public int getIndex() {
return fIndex; return fIndex;
} }
@Override @Override
public String toString() { public String toString() {
return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$
} }
} }
public static char[] getExpansion(AbstractCharArray expansionImage, int offset, int endOffset) { public static char[] getExpansion(AbstractCharArray expansionImage, int offset, int endOffset) {
TokenList tl= new TokenList(); TokenList tl= new TokenList();
Lexer lex= new Lexer(expansionImage, offset, endOffset, new LexerOptions(), ILexerLog.NULL, null); Lexer lex= new Lexer(expansionImage, offset, endOffset, new LexerOptions(), ILexerLog.NULL, null);
@ -83,7 +83,7 @@ public class MacroDefinitionParser {
buf.append(t.getCharImage()); buf.append(t.getCharImage());
endOffset= t.getEndOffset(); endOffset= t.getEndOffset();
} }
final int length= buf.length(); final int length= buf.length();
final char[] expansion= new char[length]; final char[] expansion= new char[length];
buf.getChars(0, length, expansion, 0); buf.getChars(0, length, expansion, 0);
return expansion; return expansion;
@ -93,10 +93,10 @@ public class MacroDefinitionParser {
private int fExpansionOffset; private int fExpansionOffset;
private int fExpansionEndOffset; private int fExpansionEndOffset;
private Token fNameToken; private Token fNameToken;
MacroDefinitionParser() { MacroDefinitionParser() {
} }
/** /**
* In case the name was successfully parsed, the name token is returned. * In case the name was successfully parsed, the name token is returned.
* Otherwise the return value is undefined. * Otherwise the return value is undefined.
@ -105,10 +105,10 @@ public class MacroDefinitionParser {
return fNameToken; return fNameToken;
} }
/** /**
* Parses an entire macro definition. Name must be the next token of the lexer. * Parses an entire macro definition. Name must be the next token of the lexer.
*/ */
public ObjectStyleMacro parseMacroDefinition(final Lexer lexer, final ILexerLog log) public ObjectStyleMacro parseMacroDefinition(final Lexer lexer, final ILexerLog log)
throws OffsetLimitReachedException, InvalidMacroDefinitionException { throws OffsetLimitReachedException, InvalidMacroDefinitionException {
final Token name = parseName(lexer); final Token name = parseName(lexer);
final AbstractCharArray source= lexer.getInput(); final AbstractCharArray source= lexer.getInput();
@ -122,10 +122,10 @@ public class MacroDefinitionParser {
return new FunctionStyleMacro(nameChars, paramList, fHasVarArgs, fExpansionOffset, fExpansionEndOffset, replacement, source); return new FunctionStyleMacro(nameChars, paramList, fHasVarArgs, fExpansionOffset, fExpansionEndOffset, replacement, source);
} }
/** /**
* Parses a macro definition without the replacement. Name must be the next token of the lexer. * Parses a macro definition without the replacement. Name must be the next token of the lexer.
*/ */
public PreprocessorMacro parseMacroDefinition(final Lexer lexer, final ILexerLog log, final char[] replacement) public PreprocessorMacro parseMacroDefinition(final Lexer lexer, final ILexerLog log, final char[] replacement)
throws InvalidMacroDefinitionException, OffsetLimitReachedException { throws InvalidMacroDefinitionException, OffsetLimitReachedException {
final Token name = parseName(lexer); final Token name = parseName(lexer);
@ -135,14 +135,14 @@ public class MacroDefinitionParser {
if (replacementToken.getType() != IToken.tEND_OF_INPUT) { if (replacementToken.getType() != IToken.tEND_OF_INPUT) {
throw new InvalidMacroDefinitionException(nameChars, replacementToken.getOffset(), replacementToken.getEndOffset()); throw new InvalidMacroDefinitionException(nameChars, replacementToken.getOffset(), replacementToken.getEndOffset());
} }
if (paramList == null) { if (paramList == null) {
return new ObjectStyleMacro(nameChars, replacement); return new ObjectStyleMacro(nameChars, replacement);
} }
return new FunctionStyleMacro(nameChars, paramList, fHasVarArgs, replacement); return new FunctionStyleMacro(nameChars, paramList, fHasVarArgs, replacement);
} }
/** /**
* Parses a macro definition basically checking for var-args. * Parses a macro definition basically checking for var-args.
*/ */
public static PreprocessorMacro parseMacroDefinition(final char[] name, char[][] paramList, final char[] replacement) { public static PreprocessorMacro parseMacroDefinition(final char[] name, char[][] paramList, final char[] replacement) {
@ -176,8 +176,8 @@ public class MacroDefinitionParser {
} }
} }
} }
if (paramList == null) { if (paramList == null) {
return new ObjectStyleMacro(name, replacement); return new ObjectStyleMacro(name, replacement);
} }
return new FunctionStyleMacro(name, paramList, hasVarargs, replacement); return new FunctionStyleMacro(name, paramList, hasVarargs, replacement);
@ -195,11 +195,11 @@ public class MacroDefinitionParser {
fNameToken= name; fNameToken= name;
return name; return name;
} }
private char[][] parseParamList(Lexer lex, final Token name) throws OffsetLimitReachedException, InvalidMacroDefinitionException { private char[][] parseParamList(Lexer lex, final Token name) throws OffsetLimitReachedException, InvalidMacroDefinitionException {
final Token lparen= lex.nextToken(); final Token lparen= lex.nextToken();
fHasVarArgs= FunctionStyleMacro.NO_VAARGS; fHasVarArgs= FunctionStyleMacro.NO_VAARGS;
if (lparen.getType() != IToken.tLPAREN || name.getEndOffset() != lparen.getOffset()) { if (lparen.getType() != IToken.tLPAREN || name.getEndOffset() != lparen.getOffset()) {
return null; return null;
} }
ArrayList<char[]> paramList= new ArrayList<char[]>(); ArrayList<char[]> paramList= new ArrayList<char[]>();
@ -224,7 +224,7 @@ public class MacroDefinitionParser {
paramList.add(Keywords.cVA_ARGS); paramList.add(Keywords.cVA_ARGS);
next= lex.nextToken(); next= lex.nextToken();
break; break;
case IToken.tRPAREN: case IToken.tRPAREN:
if (next == null) { if (next == null) {
next= param; next= param;
@ -255,7 +255,7 @@ public class MacroDefinitionParser {
Token needAnotherToken= null; Token needAnotherToken= null;
Token candidate= lexer.currentToken(); Token candidate= lexer.currentToken();
fExpansionOffset= fExpansionEndOffset= candidate.getOffset(); fExpansionOffset= fExpansionEndOffset= candidate.getOffset();
loop: while(true) { loop: while(true) {
switch (candidate.getType()) { switch (candidate.getType()) {
@ -266,18 +266,16 @@ public class MacroDefinitionParser {
break loop; break loop;
case IToken.tIDENTIFIER: case IToken.tIDENTIFIER:
if (paramList != null) { if (paramList != null) {
// convert the parameters to special tokens // Convert the parameters to special tokens.
final char[] image = candidate.getCharImage(); final char[] image = candidate.getCharImage();
int idx= CharArrayUtils.indexOf(image, paramList); int idx= CharArrayUtils.indexOf(image, paramList);
if (idx >= 0) { if (idx >= 0) {
candidate= new TokenParameterReference(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]); candidate= new TokenParameterReference(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]);
needParam= false; needParam= false;
} } else {
else {
if (needParam) { if (needParam) {
log.handleProblem(IProblem.PREPROCESSOR_MACRO_PASTING_ERROR, name, fExpansionOffset, candidate.getEndOffset()); log.handleProblem(IProblem.PREPROCESSOR_MACRO_PASTING_ERROR, name, fExpansionOffset, candidate.getEndOffset());
} } else if (CharArrayUtils.equals(Keywords.cVA_ARGS, image)) {
else if (CharArrayUtils.equals(Keywords.cVA_ARGS, image)) {
log.handleProblem(IProblem.PREPROCESSOR_INVALID_VA_ARGS, null, fExpansionOffset, candidate.getEndOffset()); log.handleProblem(IProblem.PREPROCESSOR_INVALID_VA_ARGS, null, fExpansionOffset, candidate.getEndOffset());
} }
needParam= false; needParam= false;

View file

@ -7,7 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,9 +35,9 @@ public class MacroExpander {
private static final class AbortMacroExpansionException extends Exception {} private static final class AbortMacroExpansionException extends Exception {}
private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION; private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION;
private static final TokenList EMPTY_TOKEN_LIST = new TokenList(); private static final TokenList EMPTY_TOKEN_LIST = new TokenList();
/** /**
* Marks the beginning and the end of the scope of a macro expansion. Necessary to properly * Marks the beginning and the end of the scope of a macro expansion. Necessary to properly
* handle recursive expansions and to figure out whether spaces are required during a stringify * handle recursive expansions and to figure out whether spaces are required during a stringify
* operation across such boundaries. * operation across such boundaries.
@ -56,7 +56,7 @@ public class MacroExpander {
public char[] getCharImage() { public char[] getCharImage() {
return CharArrayUtils.EMPTY; return CharArrayUtils.EMPTY;
} }
@Override @Override
public String toString() { public String toString() {
return "{" + (fIsStart ? '+' : '-') + fMacro.getName() + '}'; //$NON-NLS-1$ return "{" + (fIsStart ? '+' : '-') + fMacro.getName() + '}'; //$NON-NLS-1$
@ -70,8 +70,8 @@ public class MacroExpander {
} }
} }
} }
/** /**
* Combines a list of tokens with the preprocessor to form the input for macro expansion. * Combines a list of tokens with the preprocessor to form the input for macro expansion.
*/ */
private class TokenSource extends TokenList { private class TokenSource extends TokenList {
@ -112,7 +112,7 @@ public class MacroExpander {
if (fLexer != null) { if (fLexer != null) {
t= fLexer.currentToken(); t= fLexer.currentToken();
while(t.getType() == Lexer.tNEWLINE) { while (t.getType() == Lexer.tNEWLINE) {
t= fLexer.nextToken(); t= fLexer.nextToken();
} }
return t.getType() == IToken.tLPAREN; return t.getType() == IToken.tLPAREN;
@ -131,14 +131,14 @@ public class MacroExpander {
private boolean fCompletionMode; private boolean fCompletionMode;
private int fStartOffset; private int fStartOffset;
private int fEndOffset; private int fEndOffset;
// for using the expander to track expansions // for using the expander to track expansions
private String fFixedCurrentFilename; private String fFixedCurrentFilename;
private int fFixedLineNumber; private int fFixedLineNumber;
private char[] fFixedInput; private char[] fFixedInput;
private ScannerContext fReportMacros; private ScannerContext fReportMacros;
private boolean fReportUndefined; private boolean fReportUndefined;
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary,
LocationMap locationMap, LexerOptions lexOptions) { LocationMap locationMap, LexerOptions lexOptions) {
fDictionary= macroDictionary; fDictionary= macroDictionary;
@ -147,10 +147,10 @@ public class MacroExpander {
fLexOptions= lexOptions; fLexOptions= lexOptions;
fLog= log; fLog= log;
} }
/** /**
* Expects that the identifier has been consumed, stores the result in the list provided. * Expects that the identifier has been consumed, stores the result in the list provided.
* @param scannerContext * @param scannerContext
*/ */
public TokenList expand(ITokenSequence lexer, final int ppOptions, public TokenList expand(ITokenSequence lexer, final int ppOptions,
PreprocessorMacro macro, Token identifier, boolean completionMode, PreprocessorMacro macro, Token identifier, boolean completionMode,
@ -162,16 +162,16 @@ public class MacroExpander {
} else { } else {
fReportMacros= null; fReportMacros= null;
} }
fImplicitMacroExpansions.clear(); fImplicitMacroExpansions.clear();
fImageLocationInfos.clear(); fImageLocationInfos.clear();
fStartOffset= identifier.getOffset(); fStartOffset= identifier.getOffset();
fEndOffset= identifier.getEndOffset(); fEndOffset= identifier.getEndOffset();
fCompletionMode= completionMode; fCompletionMode= completionMode;
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden= new IdentityHashMap<PreprocessorMacro, PreprocessorMacro>(); IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden= new IdentityHashMap<PreprocessorMacro, PreprocessorMacro>();
// setup input sequence // setup input sequence
TokenSource input= new TokenSource(lexer); TokenSource input= new TokenSource(lexer);
TokenList firstExpansion= new TokenList(); TokenList firstExpansion= new TokenList();
@ -186,8 +186,8 @@ public class MacroExpander {
result= expandAll(input, forbidden, protectDefined, null); result= expandAll(input, forbidden, protectDefined, null);
} catch (CompletionInMacroExpansionException e) { } catch (CompletionInMacroExpansionException e) {
// For content assist in macro expansions, we return the list of tokens of the // For content assist in macro expansions, we return the list of tokens of the
// parameter at the current cursor position and hope that they make sense if // parameter at the current cursor position and hope that they make sense if
// they are inserted at the position of the expansion. // they are inserted at the position of the expansion.
// For a better solution one would have to perform the expansion with artificial // For a better solution one would have to perform the expansion with artificial
// parameters and then check where the completion token ends up in the expansion. // parameters and then check where the completion token ends up in the expansion.
@ -211,7 +211,7 @@ public class MacroExpander {
fFixedLineNumber= lineNumber; fFixedLineNumber= lineNumber;
fReportMacros= null; fReportMacros= null;
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this); Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
try { try {
tracker.start(fFixedInput); tracker.start(fFixedInput);
Token identifier= lexer.nextToken(); Token identifier= lexer.nextToken();
@ -246,21 +246,21 @@ public class MacroExpander {
} catch (OffsetLimitReachedException e) { } catch (OffsetLimitReachedException e) {
} }
} }
/** /**
* Expects that the identifier of the macro expansion has been consumed. Expands the macro * Expects that the identifier of the macro expansion has been consumed. Expands the macro
* consuming tokens from the input (to read the parameters) and stores the resulting tokens * consuming tokens from the input (to read the parameters) and stores the resulting tokens
* together with boundary markers in the result token list. * together with boundary markers in the result token list.
* @return the last token of the expansion. * @return the last token of the expansion.
* @throws AbortMacroExpansionException * @throws AbortMacroExpansionException
*/ */
private Token expandOne(Token lastConsumed, PreprocessorMacro macro, private Token expandOne(Token lastConsumed, PreprocessorMacro macro,
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input,
TokenList result, MacroExpansionTracker tracker) TokenList result, MacroExpansionTracker tracker)
throws OffsetLimitReachedException { throws OffsetLimitReachedException {
if (fReportMacros != null) if (fReportMacros != null)
fReportMacros.significantMacro(macro); fReportMacros.significantMacro(macro);
if (macro.isFunctionStyle()) { if (macro.isFunctionStyle()) {
final int paramCount = macro.getParameterPlaceholderList().length; final int paramCount = macro.getParameterPlaceholderList().length;
final TokenSource[] argInputs= new TokenSource[paramCount]; final TokenSource[] argInputs= new TokenSource[paramCount];
@ -271,13 +271,13 @@ public class MacroExpander {
try { try {
lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker); lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker);
} catch (AbortMacroExpansionException e) { } catch (AbortMacroExpansionException e) {
// ignore this macro expansion // Ignore this macro expansion.
for (TokenSource argInput : argInputs) { for (TokenSource argInput : argInputs) {
executeScopeMarkers(argInput, forbidden); executeScopeMarkers(argInput, forbidden);
if (tracker != null) { if (tracker != null) {
tracker.setExpandedMacroArgument(null); tracker.setExpandedMacroArgument(null);
} }
} }
if (tracker != null) { if (tracker != null) {
if (tracker.isRequestedStep()) { if (tracker.isRequestedStep()) {
tracker.storeFunctionStyleMacroReplacement(macro, new TokenList(), result); tracker.storeFunctionStyleMacroReplacement(macro, new TokenList(), result);
@ -288,7 +288,7 @@ public class MacroExpander {
} }
return null; return null;
} }
TokenList[] clonedArgs= new TokenList[paramCount]; TokenList[] clonedArgs= new TokenList[paramCount];
TokenList[] expandedArgs= new TokenList[paramCount]; TokenList[] expandedArgs= new TokenList[paramCount];
for (int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
@ -342,11 +342,11 @@ public class MacroExpander {
private void executeScopeMarkers(TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden) { private void executeScopeMarkers(TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden) {
Token t= input.removeFirst(); Token t= input.removeFirst();
while(t != null) { while (t != null) {
if (t.getType() == CPreprocessor.tSCOPE_MARKER) { if (t.getType() == CPreprocessor.tSCOPE_MARKER) {
((ExpansionBoundary) t).execute(forbidden); ((ExpansionBoundary) t).execute(forbidden);
} }
t= input.removeFirst(); t= input.removeFirst();
} }
} }
@ -356,7 +356,7 @@ public class MacroExpander {
boolean protect= false; boolean protect= false;
Token l= null; Token l= null;
Token t= input.removeFirst(); Token t= input.removeFirst();
while(t != null) { while (t != null) {
switch (t.getType()) { switch (t.getType()) {
case CPreprocessor.tSCOPE_MARKER: case CPreprocessor.tSCOPE_MARKER:
((ExpansionBoundary) t).execute(forbidden); ((ExpansionBoundary) t).execute(forbidden);
@ -395,7 +395,7 @@ public class MacroExpander {
addSpacemarker(l, t, replacement); // start expansion addSpacemarker(l, t, replacement); // start expansion
replacement.append(new ExpansionBoundary(macro, true)); replacement.append(new ExpansionBoundary(macro, true));
Token last= expandOne(t, macro, forbidden, input, replacement, tracker); Token last= expandOne(t, macro, forbidden, input, replacement, tracker);
replacement.append(new ExpansionBoundary(macro, false)); replacement.append(new ExpansionBoundary(macro, false));
addSpacemarker(last, input.first(), replacement); // end expansion addSpacemarker(last, input.first(), replacement); // end expansion
@ -404,12 +404,12 @@ public class MacroExpander {
break; break;
case IToken.tLPAREN: case IToken.tLPAREN:
case CPreprocessor.tNOSPACE: case CPreprocessor.tNOSPACE:
case CPreprocessor.tSPACE: case CPreprocessor.tSPACE:
result.append(t); result.append(t);
break; break;
default: default:
protect= false; protect= false;
result.append(t); result.append(t);
break; break;
} }
l= t; l= t;
@ -418,6 +418,14 @@ public class MacroExpander {
return result; return result;
} }
private void addImageLocationInfo(int offset, Token t) {
ImageLocationInfo info= createImageLocationInfo(t);
if (info != null) {
info.fTokenOffsetInExpansion= offset;
fImageLocationInfos.add(info);
}
}
private ImageLocationInfo createImageLocationInfo(Token t) { private ImageLocationInfo createImageLocationInfo(Token t) {
if (fLocationMap != null) { if (fLocationMap != null) {
final Object s= t.fSource; final Object s= t.fSource;
@ -450,26 +458,26 @@ public class MacroExpander {
} }
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0)); target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
} }
/** /**
* Expects that the identifier has been consumed. * Expects that the identifier has been consumed.
*/ */
private Token parseArguments(TokenSource input, FunctionStyleMacro macro, private Token parseArguments(TokenSource input, FunctionStyleMacro macro,
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
TokenSource[] result, MacroExpansionTracker tracker) TokenSource[] result, MacroExpansionTracker tracker)
throws OffsetLimitReachedException, AbortMacroExpansionException { throws OffsetLimitReachedException, AbortMacroExpansionException {
final int argCount= macro.getParameterPlaceholderList().length; final int argCount= macro.getParameterPlaceholderList().length;
final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS; final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
final int requiredArgs= hasVarargs ? argCount-1 : argCount; final int requiredArgs= hasVarargs ? argCount - 1 : argCount;
int idx= 0; int idx= 0;
int nesting= -1; int nesting= -1;
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
result[i]= new TokenSource(null); result[i]= new TokenSource(null);
} }
boolean missingRParenthesis= false; boolean missingRParenthesis= false;
boolean tooManyArgs= false; boolean tooManyArgs= false;
boolean isFirstOfArg= true; boolean isFirstOfArg= true;
Token lastToken= null; Token lastToken= null;
TokenList spaceMarkers= new TokenList(); TokenList spaceMarkers= new TokenList();
@ -481,7 +489,7 @@ public class MacroExpander {
} }
if (tracker != null) { if (tracker != null) {
switch (t.getType()) { switch (t.getType()) {
case IToken.tEND_OF_INPUT: case IToken.tEND_OF_INPUT:
case IToken.tCOMPLETION: case IToken.tCOMPLETION:
case CPreprocessor.tSCOPE_MARKER: case CPreprocessor.tSCOPE_MARKER:
case Lexer.tNEWLINE: case Lexer.tNEWLINE:
@ -509,28 +517,28 @@ public class MacroExpander {
throw new CompletionInMacroExpansionException(ORIGIN, t, result[idx]); throw new CompletionInMacroExpansionException(ORIGIN, t, result[idx]);
} }
throw new OffsetLimitReachedException(ORIGIN, t); throw new OffsetLimitReachedException(ORIGIN, t);
case Lexer.tNEWLINE: case Lexer.tNEWLINE:
continue loop; continue loop;
case IToken.tLPAREN: case IToken.tLPAREN:
// the first one sets nesting to zero. // The first one sets nesting to zero.
if (++nesting == 0) { if (++nesting == 0) {
continue; continue;
} }
break; break;
case IToken.tRPAREN: case IToken.tRPAREN:
assert nesting >= 0; assert nesting >= 0;
if (--nesting < 0) { if (--nesting < 0) {
break loop; break loop;
} }
break; break;
case IToken.tCOMMA: case IToken.tCOMMA:
assert nesting >= 0; assert nesting >= 0;
if (nesting == 0) { if (nesting == 0) {
if (idx < argCount-1) { // next argument if (idx < argCount - 1) { // Next argument.
isFirstOfArg= true; isFirstOfArg= true;
spaceMarkers.clear(); spaceMarkers.clear();
idx++; idx++;
@ -541,7 +549,7 @@ public class MacroExpander {
} }
} }
break; break;
case CPreprocessor.tSCOPE_MARKER: case CPreprocessor.tSCOPE_MARKER:
if (argCount == 0) { if (argCount == 0) {
((ExpansionBoundary) t).execute(forbidden); ((ExpansionBoundary) t).execute(forbidden);
@ -549,14 +557,14 @@ public class MacroExpander {
result[idx].append(t); result[idx].append(t);
} }
continue loop; continue loop;
case CPreprocessor.tSPACE: case CPreprocessor.tSPACE:
case CPreprocessor.tNOSPACE: case CPreprocessor.tNOSPACE:
if (!isFirstOfArg) { if (!isFirstOfArg) {
spaceMarkers.append(t); spaceMarkers.append(t);
} }
continue loop; continue loop;
default: default:
assert nesting >= 0; assert nesting >= 0;
} }
@ -573,7 +581,7 @@ public class MacroExpander {
handleProblem(IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, macro.getNameCharArray()); handleProblem(IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, macro.getNameCharArray());
throw new AbortMacroExpansionException(); throw new AbortMacroExpansionException();
} }
if (tooManyArgs) { if (tooManyArgs) {
handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray()); handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray());
} else if (idx + 1 < requiredArgs) { } else if (idx + 1 < requiredArgs) {
@ -581,18 +589,18 @@ public class MacroExpander {
} }
return lastToken; return lastToken;
} }
private void handleProblem(int problemID, char[] arg) { private void handleProblem(int problemID, char[] arg) {
fLog.handleProblem(problemID, arg, fStartOffset, fEndOffset); fLog.handleProblem(problemID, arg, fStartOffset, fEndOffset);
} }
private void replaceArgs(PreprocessorMacro macro, TokenList[] args, TokenList[] expandedArgs, TokenList result) { private void replaceArgs(PreprocessorMacro macro, TokenList[] args, TokenList[] expandedArgs, TokenList result) {
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this)); TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this));
Token l= null; Token l= null;
Token n; Token n;
Token pasteArg1= null; Token pasteArg1= null;
for (Token t= replacement.first(); t != null; l=t, t=n) { for (Token t= replacement.first(); t != null; l= t, t= n) {
n= (Token) t.getNext(); n= (Token) t.getNext();
switch (t.getType()) { switch (t.getType()) {
@ -614,7 +622,7 @@ public class MacroExpander {
} }
} }
break; break;
case IToken.tPOUND: case IToken.tPOUND:
addSpacemarker(l, t, result); // start stringify addSpacemarker(l, t, result); // start stringify
StringBuilder buf= new StringBuilder(); StringBuilder buf= new StringBuilder();
@ -628,19 +636,19 @@ public class MacroExpander {
n= (Token) n.getNext(); n= (Token) n.getNext();
} }
buf.append('"'); buf.append('"');
final int length= buf.length(); final int length= buf.length();
final char[] image= new char[length]; final char[] image= new char[length];
buf.getChars(0, length, image, 0); buf.getChars(0, length, image, 0);
Token generated= new TokenWithImage(IToken.tSTRING, null, 0, 0, image); Token generated= new TokenWithImage(IToken.tSTRING, null, 0, 0, image);
if (isKind(n, IToken.tPOUNDPOUND)) { // start token paste, same as start stringify if (isKind(n, IToken.tPOUNDPOUND)) { // start token paste, same as start stringify
pasteArg1= generated; pasteArg1= generated;
} else { } else {
result.append(generated); result.append(generated);
addSpacemarker(t, n, result); // end stringify addSpacemarker(t, n, result); // end stringify
} }
break; break;
case IToken.tPOUNDPOUND: case IToken.tPOUNDPOUND:
Token pasteArg2= null; Token pasteArg2= null;
TokenList rest= null; TokenList rest= null;
@ -664,7 +672,7 @@ public class MacroExpander {
idx= -1; idx= -1;
pasteArg2= n; pasteArg2= n;
} }
t= n; t= n;
n= (Token) n.getNext(); n= (Token) n.getNext();
final boolean pasteNext= isKind(n, IToken.tPOUNDPOUND); final boolean pasteNext= isKind(n, IToken.tPOUNDPOUND);
@ -676,7 +684,7 @@ public class MacroExpander {
generated= pasteArg1; generated= pasteArg1;
if (rest == null) if (rest == null)
rest= new TokenList(); rest= new TokenList();
rest.prepend(pasteArg2); rest.prepend(pasteArg2);
spaceDef0= generated; spaceDef0= generated;
spaceDef1= pasteArg2; spaceDef1= pasteArg2;
@ -707,15 +715,15 @@ public class MacroExpander {
} }
} }
break; break;
case IToken.tCOMMA: case IToken.tCOMMA:
if (isKind(n, IToken.tPOUNDPOUND)) { if (isKind(n, IToken.tPOUNDPOUND)) {
final Token nn= (Token) n.getNext(); final Token nn= (Token) n.getNext();
if (isKind(nn, CPreprocessor.tMACRO_PARAMETER)) { if (isKind(nn, CPreprocessor.tMACRO_PARAMETER)) {
idx= ((TokenParameterReference) nn).getIndex(); idx= ((TokenParameterReference) nn).getIndex();
// check for gcc-extension preventing the paste operation // check for gcc-extension preventing the paste operation
if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS && if (idx == args.length - 1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS &&
!isKind(nn.getNext(), IToken.tPOUNDPOUND)) { !isKind(nn.getNext(), IToken.tPOUNDPOUND)) {
final Token nnn= (Token) nn.getNext(); final Token nnn= (Token) nn.getNext();
TokenList arg= clone(expandedArgs[idx]); TokenList arg= clone(expandedArgs[idx]);
@ -733,14 +741,14 @@ public class MacroExpander {
break; break;
} }
} }
addSpacemarker(l, t, result); addSpacemarker(l, t, result);
pasteArg1= t; pasteArg1= t;
} else { } else {
result.append(t); result.append(t);
} }
break; break;
default: default:
if (isKind(n, IToken.tPOUNDPOUND)) { if (isKind(n, IToken.tPOUNDPOUND)) {
addSpacemarker(l, t, result); // start token paste addSpacemarker(l, t, result); // start token paste
@ -752,7 +760,7 @@ public class MacroExpander {
} }
} }
} }
private boolean isKind(final IToken t, final int kind) { private boolean isKind(final IToken t, final int kind) {
return t != null && t.getType() == kind; return t != null && t.getType() == kind;
} }
@ -760,9 +768,9 @@ public class MacroExpander {
private BitSet getParamUsage(PreprocessorMacro macro) { private BitSet getParamUsage(PreprocessorMacro macro) {
final BitSet result= new BitSet(); final BitSet result= new BitSet();
final TokenList replacement= macro.getTokens(fDefinitionParser, fLexOptions, this); final TokenList replacement= macro.getTokens(fDefinitionParser, fLexOptions, this);
Token l= null; Token l= null;
Token n; Token n;
for (Token t= replacement.first(); t != null; l= t, t= n) { for (Token t= replacement.first(); t != null; l= t, t= n) {
n= (Token) t.getNext(); n= (Token) t.getNext();
switch (t.getType()) { switch (t.getType()) {
@ -773,7 +781,7 @@ public class MacroExpander {
} }
result.set(idx); result.set(idx);
break; break;
case IToken.tPOUND: case IToken.tPOUND:
if (isKind(n, CPreprocessor.tMACRO_PARAMETER)) { if (isKind(n, CPreprocessor.tMACRO_PARAMETER)) {
idx= ((TokenParameterReference) n).getIndex(); idx= ((TokenParameterReference) n).getIndex();
@ -781,7 +789,7 @@ public class MacroExpander {
t= n; n= (Token) n.getNext(); t= n; n= (Token) n.getNext();
} }
break; break;
case IToken.tPOUNDPOUND: case IToken.tPOUNDPOUND:
if (isKind(n, CPreprocessor.tMACRO_PARAMETER)) { if (isKind(n, CPreprocessor.tMACRO_PARAMETER)) {
idx= ((TokenParameterReference) n).getIndex(); idx= ((TokenParameterReference) n).getIndex();
@ -795,17 +803,17 @@ public class MacroExpander {
t= n; n= (Token) n.getNext(); t= n; n= (Token) n.getNext();
} }
break; break;
} }
} }
return result; return result;
} }
private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) { private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this)); TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions, this));
Token l= null; Token l= null;
Token n; Token n;
Token pasteArg1= null; Token pasteArg1= null;
for (Token t= replacement.first(); t != null; l= t, t= n) { for (Token t= replacement.first(); t != null; l= t, t= n) {
n= (Token) t.getNext(); n= (Token) t.getNext();
@ -817,7 +825,7 @@ public class MacroExpander {
pasteArg2= n; pasteArg2= n;
n= (Token) n.getNext(); n= (Token) n.getNext();
} }
t= tokenpaste(pasteArg1, pasteArg2, macro); t= tokenpaste(pasteArg1, pasteArg2, macro);
if (t != null) { if (t != null) {
if (isKind(n, IToken.tPOUNDPOUND)) { if (isKind(n, IToken.tPOUNDPOUND)) {
@ -829,7 +837,7 @@ public class MacroExpander {
} }
} }
break; break;
default: default:
if (isKind(n, IToken.tPOUNDPOUND)) { if (isKind(n, IToken.tPOUNDPOUND)) {
addSpacemarker(l, t, result); // start token paste addSpacemarker(l, t, result); // start token paste
@ -910,7 +918,7 @@ public class MacroExpander {
} }
space= false; space= false;
break; break;
case CPreprocessor.tSPACE: case CPreprocessor.tSPACE:
if (!space && l != null && n != null) { if (!space && l != null && n != null) {
buf.append(' '); buf.append(' ');
@ -920,7 +928,7 @@ public class MacroExpander {
case CPreprocessor.tNOSPACE: case CPreprocessor.tNOSPACE:
break; break;
default: default:
buf.append(t.getCharImage()); buf.append(t.getCharImage());
space= false; space= false;
@ -928,7 +936,7 @@ public class MacroExpander {
} }
} }
} }
public IASTName[] clearImplicitExpansions() { public IASTName[] clearImplicitExpansions() {
IASTName[] result= fImplicitMacroExpansions.toArray(new IASTName[fImplicitMacroExpansions.size()]); IASTName[] result= fImplicitMacroExpansions.toArray(new IASTName[fImplicitMacroExpansions.size()]);
fImplicitMacroExpansions.clear(); fImplicitMacroExpansions.clear();
@ -950,20 +958,12 @@ public class MacroExpander {
case CPreprocessor.tEXPANDED_IDENTIFIER: case CPreprocessor.tEXPANDED_IDENTIFIER:
t.setType(IToken.tIDENTIFIER); t.setType(IToken.tIDENTIFIER);
if (createImageLocations) { if (createImageLocations) {
ImageLocationInfo info= createImageLocationInfo(t); addImageLocationInfo(offset, t);
if (info != null) {
info.fTokenOffsetInExpansion= offset;
fImageLocationInfos.add(info);
}
} }
break; break;
case IToken.tIDENTIFIER: case IToken.tIDENTIFIER:
if (createImageLocations) { if (createImageLocations) {
ImageLocationInfo info= createImageLocationInfo(t); addImageLocationInfo(offset, t);
if (info != null) {
info.fTokenOffsetInExpansion= offset;
fImageLocationInfos.add(info);
}
} }
break; break;
@ -978,12 +978,18 @@ public class MacroExpander {
t.setOffset(offset, offset + t.getLength()); t.setOffset(offset, offset + t.getLength());
t.setNext(null); t.setNext(null);
return; return;
default:
if (createImageLocations && t.fSource instanceof CPreprocessor) {
addImageLocationInfo(offset, t);
}
break;
} }
t.setOffset(offset, ++offset); t.setOffset(offset, ++offset);
l= t; l= t;
} }
} }
int getCurrentLineNumber() { int getCurrentLineNumber() {
if (fFixedInput != null) { if (fFixedInput != null) {
return fFixedLineNumber + countNewlines(fFixedInput); return fFixedLineNumber + countNewlines(fFixedInput);

View file

@ -7,7 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -30,12 +30,12 @@ public class MacroExpansionStep implements IMacroExpansionStep {
fMacroDefinition= def; fMacroDefinition= def;
fMacroLocation= macroLoc; fMacroLocation= macroLoc;
} }
@Override @Override
public String getCodeBeforeStep() { public String getCodeBeforeStep() {
return fBefore; return fBefore;
} }
@Override @Override
public String getCodeAfterStep() { public String getCodeAfterStep() {
StringBuilder result= new StringBuilder(); StringBuilder result= new StringBuilder();
@ -49,7 +49,7 @@ public class MacroExpansionStep implements IMacroExpansionStep {
result.append(fBefore, offset, fBefore.length()); result.append(fBefore, offset, fBefore.length());
return result.toString(); return result.toString();
} }
@Override @Override
public IMacroBinding getExpandedMacro() { public IMacroBinding getExpandedMacro() {
return fMacroDefinition; return fMacroDefinition;

View file

@ -7,7 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,7 +35,7 @@ public class MacroExpansionTracker {
} }
private final int fStepToTrack; private final int fStepToTrack;
private int fStepCount; private int fStepCount;
private String fPreStep; private String fPreStep;
private ReplaceEdit fReplacement; private ReplaceEdit fReplacement;
@ -58,14 +58,14 @@ public class MacroExpansionTracker {
public boolean isDone() { public boolean isDone() {
return fStepCount > fStepToTrack; return fStepCount > fStepToTrack;
} }
/** /**
* Returns whether we are currently looking at the requested step. * Returns whether we are currently looking at the requested step.
*/ */
public boolean isRequestedStep() { public boolean isRequestedStep() {
return fStepCount == fStepToTrack; return fStepCount == fStepToTrack;
} }
/** /**
* Returns the total amount of steps encountered so far. * Returns the total amount of steps encountered so far.
*/ */
@ -79,7 +79,7 @@ public class MacroExpansionTracker {
public String getCodeBeforeStep() { public String getCodeBeforeStep() {
return fPreStep; return fPreStep;
} }
/** /**
* Returns the replacement that represents the change by the step that was tracked. * Returns the replacement that represents the change by the step that was tracked.
*/ */
@ -132,7 +132,7 @@ public class MacroExpansionTracker {
fReplacement= new ReplaceEdit(offset, replace.length(), fReplacementText); fReplacement= new ReplaceEdit(offset, replace.length(), fReplacementText);
} }
} }
/** /**
* There was no macro at the beginning of the input. * There was no macro at the beginning of the input.
*/ */
@ -140,7 +140,7 @@ public class MacroExpansionTracker {
fPreStep= new String(fInput); fPreStep= new String(fInput);
fReplacement= new ReplaceEdit(0, 0, ""); //$NON-NLS-1$ fReplacement= new ReplaceEdit(0, 0, ""); //$NON-NLS-1$
} }
private void toString(TokenList tokenList, char[] rootInput, StringBuilder before, private void toString(TokenList tokenList, char[] rootInput, StringBuilder before,
StringBuilder replace, StringBuilder after) { StringBuilder replace, StringBuilder after) {
StringBuilder buf= before; StringBuilder buf= before;
@ -176,7 +176,7 @@ public class MacroExpansionTracker {
} }
} }
} }
private char[] getInputForSource(Object source, char[] rootInput) { private char[] getInputForSource(Object source, char[] rootInput) {
if (source instanceof MacroExpander) { if (source instanceof MacroExpander) {
return rootInput; return rootInput;
@ -197,7 +197,7 @@ public class MacroExpansionTracker {
public void startFunctionStyleMacro(Token identifier) { public void startFunctionStyleMacro(Token identifier) {
fMacroStack.add(new MacroInfo(identifier)); fMacroStack.add(new MacroInfo(identifier));
} }
/** /**
* All tokens defining a function-style macro expansion are reported. * All tokens defining a function-style macro expansion are reported.
*/ */
@ -235,7 +235,7 @@ public class MacroExpansionTracker {
* Append the current function-style macro with the arguments substituted. * Append the current function-style macro with the arguments substituted.
*/ */
public void appendFunctionStyleMacro(TokenList result) { public void appendFunctionStyleMacro(TokenList result) {
MacroInfo minfo= fMacroStack.getLast(); MacroInfo minfo= fMacroStack.getLast();
boolean active= true; boolean active= true;
int nesting= -1; int nesting= -1;
int pcount= 0; int pcount= 0;
@ -298,7 +298,7 @@ public class MacroExpansionTracker {
result.append(t); result.append(t);
} }
break; break;
default: default:
if (active) { if (active) {
result.append(t); result.append(t);

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Sergey Prigogin (Google) - initial API and implementation * Sergey Prigogin (Google) - initial API and implementation
* *
* Based on lookup3.c, by Bob Jenkins {@link "http://burtleburtle.net/bob/c/lookup3.c"} * Based on lookup3.c, by Bob Jenkins {@link "http://burtleburtle.net/bob/c/lookup3.c"}
* *
@ -44,7 +44,6 @@
* mixing with 12*3 instructions on 3 integers than you can with 3 instructions * mixing with 12*3 instructions on 3 integers than you can with 3 instructions
* on 1 byte), but shoehorning those bytes into integers efficiently is messy. * on 1 byte), but shoehorning those bytes into integers efficiently is messy.
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
/** /**

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
@ -48,7 +48,7 @@ public class Token implements IToken, Cloneable {
@Override @Override
final public int getLength() { final public int getLength() {
return fEndOffset-fOffset; return fEndOffset - fOffset;
} }
@Override @Override
@ -56,7 +56,6 @@ public class Token implements IToken, Cloneable {
return fNextToken; return fNextToken;
} }
@Override @Override
final public void setType(int kind) { final public void setType(int kind) {
fKind= kind; fKind= kind;
@ -73,8 +72,8 @@ public class Token implements IToken, Cloneable {
} }
public void shiftOffset(int shift) { public void shiftOffset(int shift) {
fOffset+= shift; fOffset += shift;
fEndOffset+= shift; fEndOffset += shift;
} }
@Override @Override
@ -86,7 +85,7 @@ public class Token implements IToken, Cloneable {
public String toString() { public String toString() {
return getImage(); return getImage();
} }
@Override @Override
final public boolean isOperator() { final public boolean isOperator() {
return TokenUtil.isOperator(fKind); return TokenUtil.isOperator(fKind);

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
class TokenList { class TokenList {
@ -17,7 +17,8 @@ class TokenList {
final Token removeFirst() { final Token removeFirst() {
final Token first= fFirst; final Token first= fFirst;
if (first == fLast) { if (first == fLast) {
fFirst= fLast= null; fFirst= null;
fLast= null;
return first; return first;
} }
fFirst= (Token) first.getNext(); fFirst= (Token) first.getNext();
@ -26,38 +27,38 @@ class TokenList {
public final void append(Token t) { public final void append(Token t) {
if (fFirst == null) { if (fFirst == null) {
fFirst= fLast= t; fFirst= t;
} fLast= t;
else { } else {
fLast.setNext(t); fLast.setNext(t);
fLast= t; fLast= t;
} }
t.setNext(null); t.setNext(null);
} }
public final void appendAll(TokenList tl) { public final void appendAll(TokenList tl) {
final Token t= tl.first(); final Token t= tl.first();
if (t != null) { if (t != null) {
if (fFirst == null) { if (fFirst == null) {
fFirst= tl.fFirst; fFirst= tl.fFirst;
} } else {
else {
fLast.setNext(tl.fFirst); fLast.setNext(tl.fFirst);
} }
fLast= tl.fLast; fLast= tl.fLast;
} }
tl.fFirst= tl.fLast= null; tl.fFirst= null;
tl.fLast= null;
} }
public final void appendAllButLast(TokenList tl) { public final void appendAllButLast(TokenList tl) {
Token t= tl.first(); Token t= tl.first();
if (t != null) { if (t != null) {
for (Token n= (Token) t.getNext(); n != null; t=n, n= (Token) n.getNext()) { for (Token n= (Token) t.getNext(); n != null; t= n, n= (Token) n.getNext()) {
append(t); append(t);
} }
} }
} }
public final void prepend(Token t) { public final void prepend(Token t) {
final Token first= t; final Token first= t;
if (first != null) { if (first != null) {
@ -81,7 +82,7 @@ class TokenList {
} }
} }
} }
public final TokenList cloneTokens() { public final TokenList cloneTokens() {
TokenList result= new TokenList(); TokenList result= new TokenList();
for (Token t= fFirst; t != null; t= (Token) t.getNext()) { for (Token t= fFirst; t != null; t= (Token) t.getNext()) {
@ -110,8 +111,7 @@ class TokenList {
fLast= null; fLast= null;
} }
} }
} } else {
else {
final Token r= (Token) l.getNext(); final Token r= (Token) l.getNext();
if (r != null) { if (r != null) {
l.setNext(r.getNext()); l.setNext(r.getNext());
@ -124,19 +124,20 @@ class TokenList {
void cutAfter(Token l) { void cutAfter(Token l) {
if (l == null) { if (l == null) {
fFirst= fLast= null; fFirst= null;
} fLast= null;
else { } else {
l.setNext(null); l.setNext(null);
fLast= l; fLast= l;
} }
} }
public void clear() { public void clear() {
fFirst= fLast= null; fFirst= null;
fLast= null;
} }
public boolean isEmpty() { public boolean isEmpty() {
return fFirst==null; return fFirst == null;
} }
} }

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.parser.IGCCToken; import org.eclipse.cdt.core.parser.IGCCToken;
@ -20,7 +20,7 @@ public class TokenUtil {
private static final char[] SPACE = {' '}; private static final char[] SPACE = {' '};
private static final char[] IMAGE_POUND_POUND = "##".toCharArray(); //$NON-NLS-1$ private static final char[] IMAGE_POUND_POUND = "##".toCharArray(); //$NON-NLS-1$
private static final char[] IMAGE_POUND = "#".toCharArray(); //$NON-NLS-1$ private static final char[] IMAGE_POUND = "#".toCharArray(); //$NON-NLS-1$
private static final char[] DIGRAPH_LBRACE= "<%".toCharArray(); //$NON-NLS-1$ private static final char[] DIGRAPH_LBRACE= "<%".toCharArray(); //$NON-NLS-1$
private static final char[] DIGRAPH_RBRACE= "%>".toCharArray(); //$NON-NLS-1$ private static final char[] DIGRAPH_RBRACE= "%>".toCharArray(); //$NON-NLS-1$
private static final char[] DIGRAPH_LBRACKET= "<:".toCharArray(); //$NON-NLS-1$ private static final char[] DIGRAPH_LBRACKET= "<:".toCharArray(); //$NON-NLS-1$
@ -40,7 +40,7 @@ public class TokenUtil {
case IToken.tSHIFTL: case IToken.tSHIFTLASSIGN: case IToken.tSHIFTL: case IToken.tSHIFTLASSIGN:
case IToken.tSHIFTR: case IToken.tSHIFTRASSIGN: case IToken.tSHIFTR: case IToken.tSHIFTRASSIGN:
case IToken.tXOR: case IToken.tXORASSIGN: case IToken.tXOR: case IToken.tXORASSIGN:
// logical operations // logical operations
case IToken.tNOT: case IToken.tAND: case IToken.tOR: case IToken.tNOT: case IToken.tAND: case IToken.tOR:
@ -52,25 +52,25 @@ public class TokenUtil {
case IToken.tPLUS: case IToken.tPLUSASSIGN: case IToken.tPLUS: case IToken.tPLUSASSIGN:
case IToken.tSTAR: case IToken.tSTARASSIGN: case IToken.tSTAR: case IToken.tSTARASSIGN:
case IGCCToken.tMAX: case IGCCToken.tMIN: case IGCCToken.tMAX: case IGCCToken.tMIN:
// comparison // comparison
case IToken.tEQUAL: case IToken.tNOTEQUAL: case IToken.tEQUAL: case IToken.tNOTEQUAL:
case IToken.tGT: case IToken.tGTEQUAL: case IToken.tGT: case IToken.tGTEQUAL:
case IToken.tLT: case IToken.tLTEQUAL: case IToken.tLT: case IToken.tLTEQUAL:
// other // other
case IToken.tASSIGN: case IToken.tCOMMA: case IToken.tASSIGN: case IToken.tCOMMA:
return true; return true;
} }
return false; return false;
} }
public static char[] getImage(int type) { public static char[] getImage(int type) {
switch (type) { switch (type) {
case IToken.tPOUND: return IMAGE_POUND; case IToken.tPOUND: return IMAGE_POUND;
case IToken.tPOUNDPOUND: return IMAGE_POUND_POUND; case IToken.tPOUNDPOUND: return IMAGE_POUND_POUND;
case IToken.tCOLONCOLON: return Keywords.cpCOLONCOLON; case IToken.tCOLONCOLON: return Keywords.cpCOLONCOLON;
case IToken.tCOLON: return Keywords.cpCOLON; case IToken.tCOLON: return Keywords.cpCOLON;
case IToken.tSEMI: return Keywords.cpSEMI; case IToken.tSEMI: return Keywords.cpSEMI;
case IToken.tCOMMA: return Keywords.cpCOMMA; case IToken.tCOMMA: return Keywords.cpCOMMA;
@ -120,34 +120,33 @@ public class TokenUtil {
case IToken.tDOT: return Keywords.cpDOT; case IToken.tDOT: return Keywords.cpDOT;
case IToken.tDIVASSIGN: return Keywords.cpDIVASSIGN; case IToken.tDIVASSIGN: return Keywords.cpDIVASSIGN;
case IToken.tDIV: return Keywords.cpDIV; case IToken.tDIV: return Keywords.cpDIV;
case IGCCToken.tMIN: return Keywords.cpMIN; case IGCCToken.tMIN: return Keywords.cpMIN;
case IGCCToken.tMAX: return Keywords.cpMAX; case IGCCToken.tMAX: return Keywords.cpMAX;
case CPreprocessor.tSPACE: return SPACE; case CPreprocessor.tSPACE: return SPACE;
case CPreprocessor.tNOSPACE: return CharArrayUtils.EMPTY; case CPreprocessor.tNOSPACE: return CharArrayUtils.EMPTY;
default: default:
return CharArrayUtils.EMPTY; return CharArrayUtils.EMPTY;
} }
} }
public static char[] getDigraphImage(int type) { public static char[] getDigraphImage(int type) {
switch (type) { switch (type) {
case IToken.tPOUND: return DIGRAPH_POUND; case IToken.tPOUND: return DIGRAPH_POUND;
case IToken.tPOUNDPOUND: return DIGRAPH_POUNDPOUND; case IToken.tPOUNDPOUND: return DIGRAPH_POUNDPOUND;
case IToken.tLBRACKET: return DIGRAPH_LBRACKET; case IToken.tLBRACKET: return DIGRAPH_LBRACKET;
case IToken.tRBRACKET: return DIGRAPH_RBRACKET; case IToken.tRBRACKET: return DIGRAPH_RBRACKET;
case IToken.tLBRACE: return DIGRAPH_LBRACE; case IToken.tLBRACE: return DIGRAPH_LBRACE;
case IToken.tRBRACE: return DIGRAPH_RBRACE; case IToken.tRBRACE: return DIGRAPH_RBRACE;
default: default:
assert false: type; assert false: type;
return CharArrayUtils.EMPTY; return CharArrayUtils.EMPTY;
} }
} }
/** /**
* Returns the last token in the given token list. * Returns the last token in the given token list.
* @throws NullPointerException if the argument is null * @throws NullPointerException if the argument is null
@ -156,8 +155,7 @@ public class TokenUtil {
IToken last; IToken last;
do { do {
last = tokenList; last = tokenList;
} while((tokenList = tokenList.getNext()) != null); } while ((tokenList = tokenList.getNext()) != null);
return last; return last;
} }
} }

View file

@ -214,7 +214,7 @@ public final class TypeMarshalBuffer implements ITypeMarshalBuffer {
fPos--; fPos--;
IType type = unmarshalType(); IType type = unmarshalType();
IType originalType = unmarshalType(); IType originalType = unmarshalType();
if (originalType == null) if (originalType == null || originalType == UNSTORABLE_TYPE_PROBLEM)
originalType= type; originalType= type;
return new CPPTemplateTypeArgument(type, originalType); return new CPPTemplateTypeArgument(type, originalType);
} }

View file

@ -66,6 +66,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTNullStatement; import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
@ -143,6 +144,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.formatter.align.Alignment; import org.eclipse.cdt.internal.formatter.align.Alignment;
import org.eclipse.cdt.internal.formatter.align.AlignmentException; import org.eclipse.cdt.internal.formatter.align.AlignmentException;
@ -232,6 +234,28 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
} }
private static class TokenRange {
private int offset;
private int endOffset;
TokenRange(int offset, int endOffset) {
this.offset = offset;
this.endOffset = endOffset;
}
int getOffset() {
return offset;
}
int getEndOffset() {
return endOffset;
}
int getLength() {
return endOffset - offset;
}
}
/** /**
* Formats a trailing semicolon. * Formats a trailing semicolon.
* @see #formatList(List, ListOptions, boolean, boolean, Runnable) * @see #formatList(List, ListOptions, boolean, boolean, Runnable)
@ -360,6 +384,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
private final Scribe scribe; private final Scribe scribe;
private boolean fInsideFor; private boolean fInsideFor;
private boolean fInsideMacroArguments;
private boolean fExpectSemicolonAfterDeclaration= true; private boolean fExpectSemicolonAfterDeclaration= true;
private MultiStatus fStatus; private MultiStatus fStatus;
@ -540,97 +565,79 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
if (fileLocation != null) { if (fileLocation != null) {
scribe.printRaw(fileLocation.getNodeOffset(), fileLocation.getNodeLength()); scribe.printRaw(fileLocation.getNodeOffset(), fileLocation.getNodeLength());
} }
fileLocation = macroExpansion.getFileLocation();
scribe.printNextToken(Token.tLPAREN);
IMacroBinding binding = (IMacroBinding) name.resolveBinding(); IMacroBinding binding = (IMacroBinding) name.resolveBinding();
if (preferences.insert_space_after_opening_paren_in_method_invocation) { List<Object> arguments = getMacroArguments(binding.getParameterList().length);
scribe.space();
final ListOptions options= new ListOptions(preferences.alignment_for_arguments_in_method_invocation);
options.fSeparatorToken = Token.tCOMMA;
options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_invocation;
options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_invocation;
options.fSpaceBetweenEmptyParen= preferences.insert_space_between_empty_parens_in_method_invocation;
options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_method_invocation_arguments;
options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_method_invocation_arguments;
options.fTieBreakRule = Alignment.R_OUTERMOST;
fInsideMacroArguments = true;
try {
formatList(arguments, options, true, false, scribe.takeTailFormatter());
} finally {
fInsideMacroArguments = false;
} }
final int continuationIndentation = preferences.continuation_indentation; }
Alignment listAlignment = scribe.createAlignment(
Alignment.MACRO_ARGUMENTS, /**
preferences.alignment_for_arguments_in_method_invocation, * Scans macro expansion arguments starting from the current position and returns a list of
Alignment.R_OUTERMOST, * arguments where each argument is represented either by a {@link IASTNode} or, if not
binding.getParameterList().length, * possible, by a {@link TokenRange}.
getCurrentPosition(), */
continuationIndentation, private List<Object> getMacroArguments(int expectedNumberOfArguments) {
false); List<TokenRange> argumentRanges = new ArrayList<TokenRange>(expectedNumberOfArguments);
scribe.enterAlignment(listAlignment); TokenRange currentArgument = null;
boolean ok = false; localScanner.resetTo(getCurrentPosition(), scribe.scannerEndPosition);
do { localScanner.getNextToken(); // Skip the opening parenthesis.
try { int parenLevel = 0;
int fragment = 0; int token;
scribe.alignFragment(listAlignment, fragment); while ((token = localScanner.getNextToken()) != Token.tBADCHAR) {
int parenLevel= 0; int tokenOffset = localScanner.getCurrentTokenStartPosition();
boolean done = false; if (parenLevel == 0 && (token == Token.tCOMMA || token == Token.tRPAREN)) {
while (!done) { if (currentArgument != null) {
boolean hasWhitespace= scribe.printComment(); argumentRanges.add(currentArgument);
int token = peekNextToken(); currentArgument = null;
switch (token) { } else {
case Token.tLPAREN: argumentRanges.add(new TokenRange(tokenOffset, tokenOffset));
++parenLevel;
scribe.printNextToken(token, hasWhitespace);
break;
case Token.tRPAREN:
if (parenLevel > 0) {
--parenLevel;
scribe.printNextToken(token, hasWhitespace);
} else {
if (preferences.insert_space_before_closing_paren_in_method_invocation) {
scribe.space();
}
scribe.printNextToken(token);
done = true;
}
break;
case Token.tCOMMA:
if (parenLevel == 0 && preferences.insert_space_before_comma_in_method_invocation_arguments) {
scribe.space();
}
scribe.printNextToken(token);
if (parenLevel == 0) {
if (preferences.insert_space_after_comma_in_method_invocation_arguments) {
scribe.space();
}
scribe.printComment();
++fragment;
if (fragment < listAlignment.fragmentCount) {
scribe.alignFragment(listAlignment, fragment);
}
}
break;
case Token.tSTRING:
case Token.tLSTRING:
case Token.tRSTRING:
boolean needSpace= hasWhitespace;
while (true) {
scribe.printNextToken(token, needSpace);
if (peekNextToken() != token) {
break;
}
scribe.printCommentPreservingNewLines();
needSpace= true;
}
break;
case Token.tBADCHAR:
// Avoid infinite loop if something bad happened.
scribe.exitAlignment(listAlignment, true);
return;
default:
scribe.printNextToken(token, hasWhitespace);
}
} }
int token = peekNextToken(); if (token == Token.tRPAREN)
if (token == Token.tSEMI) { break;
scribe.printNextToken(token); } else {
scribe.startNewLine(); int tokenEndOffset = localScanner.getCurrentPosition();
if (currentArgument == null) {
currentArgument = new TokenRange(tokenOffset, tokenEndOffset);
} else {
currentArgument.endOffset = tokenEndOffset;
}
switch (token) {
case Token.tLPAREN:
++parenLevel;
break;
case Token.tRPAREN:
if (parenLevel > 0)
--parenLevel;
break;
} }
ok = true;
} catch (AlignmentException e) {
scribe.redoAlignment(e);
} }
} while (!ok); }
scribe.exitAlignment(listAlignment, true);
List<Object> arguments = new ArrayList<Object>(argumentRanges.size());
IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
for (TokenRange argument : argumentRanges) {
IASTNode node = nodeSelector.findNodeInExpansion(argument.getOffset(), argument.getLength());
if (node != null) {
arguments.add(node);
} else {
arguments.add(argument);
}
}
return arguments;
} }
@Override @Override
@ -2077,15 +2084,16 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/** /**
* Format a given list of elements according alignment options. * Format a given list of elements according alignment options.
* *
* @param elements the elements to format * @param elements the elements to format, which can be either {@link IASTNode}s or
* {@link TokenRange}s.
* @param options formatting options * @param options formatting options
* @param encloseInParen indicates whether the list should be enclosed in parentheses * @param encloseInParen indicates whether the list should be enclosed in parentheses
* @param addEllipsis indicates whether ellipsis should be added after the last element * @param addEllipsis indicates whether ellipsis should be added after the last element
* @param tailFormatter formatter for the trailing text that should be kept together with * @param tailFormatter formatter for the trailing text that should be kept together with
* the last element of the list. * the last element of the list.
*/ */
private void formatList(List<? extends IASTNode> elements, ListOptions options, private void formatList(List<?> elements, ListOptions options, boolean encloseInParen,
boolean encloseInParen, boolean addEllipsis, Runnable tailFormatter) { boolean addEllipsis, Runnable tailFormatter) {
if (encloseInParen) if (encloseInParen)
scribe.printNextToken(Token.tLPAREN, options.fSpaceBeforeOpeningParen); scribe.printNextToken(Token.tLPAREN, options.fSpaceBeforeOpeningParen);
@ -2118,22 +2126,26 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
try { try {
int i; int i;
for (i = 0; i < elementsLength; i++) { for (i = 0; i < elementsLength; i++) {
final IASTNode node= elements.get(i); final Object element = elements.get(i);
if (i < elementsLength - 1) { if (i < elementsLength - 1) {
scribe.setTailFormatter( scribe.setTailFormatter(
new TrailingTokenFormatter(options.fSeparatorToken, new TrailingTokenFormatter(options.fSeparatorToken,
findTokenAfterNode(options.fSeparatorToken, node), findTokenAfterNodeOrTokenRange(options.fSeparatorToken, element),
options.fSpaceBeforeSeparator, options.fSpaceBeforeSeparator,
options.fSpaceAfterSeparator)); options.fSpaceAfterSeparator));
} else { } else {
scribe.setTailFormatter(tailFormatter); scribe.setTailFormatter(tailFormatter);
} }
scribe.alignFragment(alignment, i); scribe.alignFragment(alignment, i);
if (node instanceof ICPPASTConstructorChainInitializer) { if (element instanceof IASTNode) {
// Constructor chain initializer is a special case. if (element instanceof ICPPASTConstructorChainInitializer) {
visit((ICPPASTConstructorChainInitializer) node); // Constructor chain initializer is a special case.
visit((ICPPASTConstructorChainInitializer) element);
} else {
((IASTNode) element).accept(this);
}
} else { } else {
node.accept(this); formatTokenRange((TokenRange) element);
} }
if (i < elementsLength - 1) { if (i < elementsLength - 1) {
scribe.runTailFormatter(); scribe.runTailFormatter();
@ -2163,6 +2175,15 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
} }
private void formatTokenRange(TokenRange tokenRange) {
scribe.restartAtOffset(tokenRange.getOffset());
while (getCurrentPosition() < tokenRange.getEndOffset()) {
boolean hasWhitespace= scribe.printComment();
int token = peekNextToken();
scribe.printNextToken(token, hasWhitespace);
}
}
private int visit(ICPPASTTryBlockStatement node) { private int visit(ICPPASTTryBlockStatement node) {
scribe.printNextToken(Token.t_try, scribe.printComment()); scribe.printNextToken(Token.t_try, scribe.printComment());
final IASTStatement tryBody= node.getTryBody(); final IASTStatement tryBody= node.getTryBody();
@ -3782,18 +3803,23 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
IASTNodeLocation[] locations= node.getNodeLocations(); IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) { if (locations.length == 0) {
} else if (locations[0] instanceof IASTMacroExpansionLocation) { } else if (!fInsideMacroArguments && locations[0] instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation location = (IASTMacroExpansionLocation) locations[0]; IASTMacroExpansionLocation location = (IASTMacroExpansionLocation) locations[0];
if (locations.length <= 2 && node instanceof IASTStatement) { if (locations.length <= 2 && node instanceof IASTStatement) {
IASTPreprocessorMacroExpansion macroExpansion = location.getExpansion(); IASTPreprocessorMacroExpansion macroExpansion = location.getExpansion();
IASTFileLocation macroLocation = macroExpansion.getFileLocation(); IASTFileLocation macroLocation = macroExpansion.getFileLocation();
IASTFileLocation nodeLocation = node.getFileLocation(); IASTFileLocation nodeLocation = getFileLocation(node);
if (macroLocation.getNodeOffset() >= getCurrentPosition() && if (macroLocation.getNodeOffset() >= getCurrentPosition() &&
!scribe.shouldSkip(macroLocation.getNodeOffset()) && !scribe.shouldSkip(macroLocation.getNodeOffset()) &&
(nodeLocation.getNodeOffset() + nodeLocation.getNodeLength() == (nodeLocation.getNodeOffset() + nodeLocation.getNodeLength() ==
macroLocation.getNodeOffset() + macroLocation.getNodeLength() || macroLocation.getNodeOffset() + macroLocation.getNodeLength() ||
locations.length == 2 && isSemicolonLocation(locations[1])) && locations.length == 2 && isSemicolonLocation(locations[1])) &&
isFunctionStyleMacroExpansion(macroExpansion)) { isFunctionStyleMacroExpansion(macroExpansion)) {
if (locations.length == 2 && isSemicolonLocation(locations[1])) {
scribe.setTailFormatter(
new TrailingTokenFormatter(Token.tSEMI, locations[1].getNodeOffset(),
preferences.insert_space_before_semicolon, false));
}
formatFunctionStyleMacroExpansion(macroExpansion); formatFunctionStyleMacroExpansion(macroExpansion);
return false; return false;
} }
@ -3808,12 +3834,16 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return false; return false;
} }
} else { } else {
IASTFileLocation fileLocation= node.getFileLocation(); IASTFileLocation fileLocation= getFileLocation(node);
scribe.restartAtOffset(fileLocation.getNodeOffset()); scribe.restartAtOffset(fileLocation.getNodeOffset());
} }
return true; return true;
} }
private IASTFileLocation getFileLocation(IASTNode node) {
return fInsideMacroArguments ? ((ASTNode) node).getImageLocation() : node.getFileLocation();
}
/** /**
* Formatting of node is complete. Undo skip region if any. * Formatting of node is complete. Undo skip region if any.
* *
@ -3824,7 +3854,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return; return;
} }
if (scribe.skipRange()) { if (scribe.skipRange()) {
IASTFileLocation fileLocation= node.getFileLocation(); IASTFileLocation fileLocation= getFileLocation(node);
if (fileLocation != null) { if (fileLocation != null) {
int nodeEndOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength(); int nodeEndOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength();
scribe.restartAtOffset(nodeEndOffset); scribe.restartAtOffset(nodeEndOffset);
@ -3845,7 +3875,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
if (node instanceof IASTProblemHolder || node instanceof IASTTranslationUnit) { if (node instanceof IASTProblemHolder || node instanceof IASTTranslationUnit) {
return; return;
} }
IASTFileLocation fileLocation= node.getFileLocation(); IASTFileLocation fileLocation= getFileLocation(node);
if (fileLocation == null) { if (fileLocation == null) {
return; return;
} }
@ -3855,20 +3885,22 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
if (currentOffset > nodeEndOffset) { if (currentOffset > nodeEndOffset) {
return; return;
} }
IASTNodeLocation[] locations= node.getNodeLocations(); if (!fInsideMacroArguments) {
for (int i= 0; i < locations.length; i++) { IASTNodeLocation[] locations= node.getNodeLocations();
IASTNodeLocation nodeLocation= locations[i]; for (int i= 0; i < locations.length; i++) {
if (nodeLocation instanceof IASTMacroExpansionLocation) { IASTNodeLocation nodeLocation= locations[i];
IASTFileLocation expansionLocation= nodeLocation.asFileLocation(); if (nodeLocation instanceof IASTMacroExpansionLocation) {
int startOffset= expansionLocation.getNodeOffset(); IASTFileLocation expansionLocation= nodeLocation.asFileLocation();
int endOffset= startOffset + expansionLocation.getNodeLength(); int startOffset= expansionLocation.getNodeOffset();
if (currentOffset <= startOffset) { int endOffset= startOffset + expansionLocation.getNodeLength();
break; if (currentOffset <= startOffset) {
} break;
if (currentOffset < endOffset || }
currentOffset == endOffset && i == locations.length - 1) { if (currentOffset < endOffset ||
scribe.skipRange(startOffset, endOffset); currentOffset == endOffset && i == locations.length - 1) {
break; scribe.skipRange(startOffset, endOffset);
break;
}
} }
} }
} }
@ -3881,7 +3913,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
private void skipNode(IASTNode node) { private void skipNode(IASTNode node) {
final IASTNodeLocation fileLocation= node.getFileLocation(); final IASTNodeLocation fileLocation= getFileLocation(node);
if (fileLocation != null && fileLocation.getNodeLength() > 0) { if (fileLocation != null && fileLocation.getNodeLength() > 0) {
final int endOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength(); final int endOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength();
final int currentOffset= getCurrentPosition(); final int currentOffset= getCurrentPosition();
@ -3893,7 +3925,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
private void skipToNode(IASTNode node) { private void skipToNode(IASTNode node) {
final IASTNodeLocation fileLocation= node.getFileLocation(); final IASTNodeLocation fileLocation= getFileLocation(node);
if (fileLocation != null) { if (fileLocation != null) {
final int startOffset= fileLocation.getNodeOffset(); final int startOffset= fileLocation.getNodeOffset();
final int currentOffset= getCurrentPosition(); final int currentOffset= getCurrentPosition();
@ -3905,7 +3937,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
private void skipNonWhitespaceToNode(IASTNode node) { private void skipNonWhitespaceToNode(IASTNode node) {
final IASTNodeLocation fileLocation= node.getFileLocation(); final IASTNodeLocation fileLocation= getFileLocation(node);
if (fileLocation != null) { if (fileLocation != null) {
final int startOffset= fileLocation.getNodeOffset(); final int startOffset= fileLocation.getNodeOffset();
final int nextTokenOffset= getNextTokenOffset(); final int nextTokenOffset= getNextTokenOffset();
@ -3985,18 +4017,22 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
} }
private static boolean startsWithMacroExpansion(IASTNode node) { private boolean startsWithMacroExpansion(IASTNode node) {
if (fInsideMacroArguments)
return false;
IASTNodeLocation[] locations= node.getNodeLocations(); IASTNodeLocation[] locations= node.getNodeLocations();
if (!(node instanceof IASTProblemHolder) && locations.length != 0 && if (!(node instanceof IASTProblemHolder) && locations.length != 0 &&
locations[0] instanceof IASTMacroExpansionLocation) { locations[0] instanceof IASTMacroExpansionLocation) {
IASTFileLocation expansionLocation= locations[0].asFileLocation(); IASTFileLocation expansionLocation= locations[0].asFileLocation();
IASTFileLocation fileLocation= node.getFileLocation(); IASTFileLocation fileLocation= getFileLocation(node);
return expansionLocation.getNodeOffset() == fileLocation.getNodeOffset(); return expansionLocation.getNodeOffset() == fileLocation.getNodeOffset();
} }
return false; return false;
} }
private static boolean endsWithMacroExpansion(IASTNode node) { private boolean endsWithMacroExpansion(IASTNode node) {
if (fInsideMacroArguments)
return false;
IASTNodeLocation[] locations= node.getNodeLocations(); IASTNodeLocation[] locations= node.getNodeLocations();
if (!(node instanceof IASTProblemHolder) && locations.length != 0 && if (!(node instanceof IASTProblemHolder) && locations.length != 0 &&
locations[locations.length - 1] instanceof IASTMacroExpansionLocation) { locations[locations.length - 1] instanceof IASTMacroExpansionLocation) {
@ -4005,13 +4041,17 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return false; return false;
} }
private static boolean enclosedInMacroExpansion(IASTNode node) { private boolean enclosedInMacroExpansion(IASTNode node) {
if (fInsideMacroArguments)
return false;
IASTNodeLocation[] locations= node.getNodeLocations(); IASTNodeLocation[] locations= node.getNodeLocations();
return locations.length == 1 && locations[0] instanceof IASTMacroExpansionLocation; return locations.length == 1 && locations[0] instanceof IASTMacroExpansionLocation;
} }
private static boolean withinMacroExpansion(IASTNode node, int offset) { private boolean withinMacroExpansion(IASTNode node, int offset) {
IASTFileLocation loc = node.getFileLocation(); if (fInsideMacroArguments)
return false;
IASTFileLocation loc = getFileLocation(node);
if (loc == null || offset < loc.getNodeOffset() || offset >= loc.getNodeOffset() + loc.getNodeLength()) { if (loc == null || offset < loc.getNodeOffset() || offset >= loc.getNodeOffset() + loc.getNodeLength()) {
return false; return false;
} }
@ -4061,9 +4101,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
* normally separated by other tokens this is an indication that they were produced by the same * normally separated by other tokens this is an indication that they were produced by the same
* macro expansion. * macro expansion.
*/ */
private static boolean doNodeLocationsOverlap(IASTNode node1, IASTNode node2) { private boolean doNodeLocationsOverlap(IASTNode node1, IASTNode node2) {
IASTFileLocation loc1 = node1.getFileLocation(); IASTFileLocation loc1 = getFileLocation(node1);
IASTFileLocation loc2 = node2.getFileLocation(); IASTFileLocation loc2 = getFileLocation(node2);
return loc1.getNodeOffset() + loc1.getNodeLength() > loc2.getNodeOffset() && return loc1.getNodeOffset() + loc1.getNodeLength() > loc2.getNodeOffset() &&
loc1.getNodeOffset() < loc2.getNodeOffset() + loc2.getNodeLength(); loc1.getNodeOffset() < loc2.getNodeOffset() + loc2.getNodeLength();
} }
@ -4073,16 +4113,16 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
* separated by other tokens this is an indication that they were produced by the same macro * separated by other tokens this is an indication that they were produced by the same macro
* expansion. * expansion.
*/ */
private static boolean doNodesHaveSameOffset(IASTNode node1, IASTNode node2) { private boolean doNodesHaveSameOffset(IASTNode node1, IASTNode node2) {
return nodeOffset(node1) == nodeOffset(node2); return nodeOffset(node1) == nodeOffset(node2);
} }
private static int nodeOffset(IASTNode node) { private int nodeOffset(IASTNode node) {
return node.getFileLocation().getNodeOffset(); return getFileLocation(node).getNodeOffset();
} }
private static int nodeEndOffset(IASTNode node) { private int nodeEndOffset(IASTNode node) {
IASTFileLocation loc = node.getFileLocation(); IASTFileLocation loc = getFileLocation(node);
return loc.getNodeOffset() + loc.getNodeLength(); return loc.getNodeOffset() + loc.getNodeLength();
} }
@ -4407,14 +4447,19 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
private int findTokenWithinNode(int tokenType, IASTNode node) { private int findTokenWithinNode(int tokenType, IASTNode node) {
IASTFileLocation location = node.getFileLocation(); IASTFileLocation location = getFileLocation(node);
int endOffset = location.getNodeOffset() + location.getNodeLength(); int endOffset = location.getNodeOffset() + location.getNodeLength();
return scribe.findToken(tokenType, endOffset); return scribe.findToken(tokenType, endOffset);
} }
private int findTokenAfterNode(int tokenType, IASTNode node) { private int findTokenAfterNodeOrTokenRange(int tokenType, Object nodeOrTokenRange) {
IASTFileLocation location = node.getFileLocation(); int startOffset;
int startOffset = location.getNodeOffset() + location.getNodeLength(); if (nodeOrTokenRange instanceof IASTNode) {
IASTFileLocation location = getFileLocation((IASTNode) nodeOrTokenRange);
startOffset = location.getNodeOffset() + location.getNodeLength();
} else {
startOffset = ((TokenRange) nodeOrTokenRange).getEndOffset();
}
return scribe.findToken(tokenType, startOffset, scribe.scannerEndPosition - 1); return scribe.findToken(tokenType, startOffset, scribe.scannerEndPosition - 1);
} }
} }

View file

@ -1765,7 +1765,6 @@ public class CodeFormatterTest extends BaseUITestCase {
// } // }
//#endif //#endif
//} //}
public void testMacroAsFunctionArguments_Bug253039() throws Exception { public void testMacroAsFunctionArguments_Bug253039() throws Exception {
assertFormatterResult(); assertFormatterResult();
} }
@ -1901,6 +1900,33 @@ public class CodeFormatterTest extends BaseUITestCase {
assertFormatterResult(); assertFormatterResult();
} }
//#define MACRO(a,b) f(a,b)
//void f(bool b, int i);
//int function_with_loooooooooooooooong_name();
//int another_function_with_loooooong_name();
//
//void test(){
// MACRO("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"=="bbbbbbbbbbbbbbbbbbbbbbbbbbb",function_with_loooooooooooooooong_name()+another_function_with_loooooong_name());
//}
//#define MACRO(a,b) f(a,b)
//void f(bool b, int i);
//int function_with_loooooooooooooooong_name();
//int another_function_with_loooooong_name();
//
//void test() {
// MACRO("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
// == "bbbbbbbbbbbbbbbbbbbbbbbbbbb",
// function_with_loooooooooooooooong_name()
// + another_function_with_loooooong_name());
//}
public void testMacroArguments() throws Exception {
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION,
Integer.toString(Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN));
assertFormatterResult();
}
//bool member __attribute__ ((__unused__)) = false; //bool member __attribute__ ((__unused__)) = false;
//bool member __attribute__ ((__unused__)) = false; //bool member __attribute__ ((__unused__)) = false;
@ -2892,7 +2918,7 @@ public class CodeFormatterTest extends BaseUITestCase {
//void f() { //void f() {
// if (1) { // if (1) {
// } // }
// IF(1>0); // IF(1 > 0);
//} //}
public void testMacroAfterCompoundStatement_Bug356690() throws Exception { public void testMacroAfterCompoundStatement_Bug356690() throws Exception {
assertFormatterResult(); assertFormatterResult();

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2012 IBM Corporation and others. * Copyright (c) 2004, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -96,8 +96,8 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
fCFile= null; fCFile= null;
super.tearDown(); super.tearDown();
} }
protected void assertContentAssistResults(int offset, int length, String[] expected, boolean isCompletion, boolean isTemplate, int compareType) throws Exception { protected void assertContentAssistResults(int offset, int length, String[] expected, boolean isCompletion, boolean isTemplate, boolean filterResults, int compareType) throws Exception {
if (CTestPlugin.getDefault().isDebugging()) { if (CTestPlugin.getDefault().isDebugging()) {
System.out.println("\n\n\n\n\nTesting "+this.getClass().getName()); System.out.println("\n\n\n\n\nTesting "+this.getClass().getName());
} }
@ -116,10 +116,12 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
long endTime= System.currentTimeMillis(); long endTime= System.currentTimeMillis();
assertTrue(results != null); assertTrue(results != null);
if(isTemplate) { if (filterResults) {
results= filterResultsKeepTemplates(results); if (isTemplate) {
} else { results= filterResultsKeepTemplates(results);
results= filterResults(results, isCode); } else {
results= filterResults(results, isCode);
}
} }
String[] resultStrings= toStringArray(results, compareType); String[] resultStrings= toStringArray(results, compareType);
Arrays.sort(expected); Arrays.sort(expected);
@ -160,6 +162,10 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
} }
} }
protected void assertContentAssistResults(int offset, int length, String[] expected, boolean isCompletion, boolean isTemplate, int compareType) throws Exception {
assertContentAssistResults(offset, length, expected, isCompletion, isTemplate, true, compareType);
}
protected void assertContentAssistResults(int offset, String[] expected, boolean isCompletion, int compareType) throws Exception { protected void assertContentAssistResults(int offset, String[] expected, boolean isCompletion, int compareType) throws Exception {
assertContentAssistResults(offset, 0, expected, isCompletion, false, compareType); assertContentAssistResults(offset, 0, expected, isCompletion, false, compareType);

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2012 Wind River Systems, Inc. and others. * Copyright (c) 2006, 2013 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -1374,4 +1374,10 @@ public class CompletionTests extends AbstractContentAssistTest {
final String[] expected= { "foo;" }; final String[] expected= { "foo;" };
assertCompletionResults(fCursorOffset, expected, COMPARE_REP_STRINGS); assertCompletionResults(fCursorOffset, expected, COMPARE_REP_STRINGS);
} }
// template <typen/*cursor*/
public void testTemplateDeclaration_Bug397288() throws Exception {
final String[] expected= { "typename" };
assertContentAssistResults(fCursorOffset, 0, expected, true, false, false, COMPARE_REP_STRINGS);
}
} }

View file

@ -1081,11 +1081,13 @@ public class LanguageSettingsProviderTab extends AbstractCPropertyTab {
return; return;
ICConfigurationDescription cfgDescription = getConfigurationDescription(); ICConfigurationDescription cfgDescription = getConfigurationDescription();
String cfgId = cfgDescription.getId(); if (cfgDescription != null) {
if (!initialProvidersByCfg.containsKey(cfgId)) { String cfgId = cfgDescription.getId();
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { if (!initialProvidersByCfg.containsKey(cfgId)) {
List<ILanguageSettingsProvider> initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
initialProvidersByCfg.put(cfgId, initialProviders); List<ILanguageSettingsProvider> initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
initialProvidersByCfg.put(cfgId, initialProviders);
}
} }
} }

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.dsf.gdb.service;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
@ -169,72 +170,117 @@ public class GDBBreakpoints_7_4 extends GDBBreakpoints_7_2 implements IEventList
} }
@Override @Override
protected void addBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> finalRm) { protected void addBreakpoint(
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); final IBreakpointsTargetDMContext context,
final Map<String, Object> attributes,
final DataRequestMonitor<IBreakpointDMContext> finalRm) {
final MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
if (bs != null) { if (bs != null) {
// Skip the breakpoints set from the console or from outside of Eclipse // Skip the breakpoints set from the console or from outside of Eclipse
// because they are already installed on the target. // because they are already installed on the target.
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes); bs.getTargetBreakpoint(
if (miBpt != null) { context,
bs.removeCreatedTargetBreakpoint(context, miBpt); attributes,
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); new DataRequestMonitor<MIBreakpoint>(getExecutor(), finalRm) {
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); @Override
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); @ConfinedToDsfExecutor( "fExecutor" )
finalRm.setData(dmc); protected void handleSuccess() {
MIBreakpoint miBpt = getData();
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt);
finalRm.done(); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
return; getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
} IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
finalRm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
finalRm.done();
}
else {
GDBBreakpoints_7_4.super.addBreakpoint(context, attributes, finalRm);
}
}
});
}
else {
super.addBreakpoint(context, attributes, finalRm);
} }
super.addBreakpoint(context, attributes, finalRm);
} }
@Override @Override
protected void addTracepoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> drm) { protected void addTracepoint(
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); final IBreakpointsTargetDMContext context,
final Map<String, Object> attributes,
final DataRequestMonitor<IBreakpointDMContext> drm) {
final MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
if (bs != null) { if (bs != null) {
// Skip the breakpoints set from the console or from outside of Eclipse // Skip the breakpoints set from the console or from outside of Eclipse
// because they are already installed on the target. // because they are already installed on the target.
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes); bs.getTargetBreakpoint(
if (miBpt != null) { context,
bs.removeCreatedTargetBreakpoint(context, miBpt); attributes,
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); new DataRequestMonitor<MIBreakpoint>(getExecutor(), drm) {
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); @Override
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); @ConfinedToDsfExecutor( "fExecutor" )
drm.setData(dmc); protected void handleSuccess() {
MIBreakpoint miBpt = getData();
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt);
drm.done(); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
return; getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
} IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
drm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
drm.done();
}
else {
GDBBreakpoints_7_4.super.addTracepoint(context, attributes, drm);
}
}
});
}
else {
super.addTracepoint(context, attributes, drm);
} }
super.addTracepoint(context, attributes, drm);
} }
@Override @Override
protected void addWatchpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> drm) { protected void addWatchpoint(
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); final IBreakpointsTargetDMContext context,
final Map<String, Object> attributes,
final DataRequestMonitor<IBreakpointDMContext> drm) {
final MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
if (bs != null) { if (bs != null) {
// Skip the breakpoints set from the console or from outside of Eclipse // Skip the breakpoints set from the console or from outside of Eclipse
// because they are already installed on the target. // because they are already installed on the target.
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes); bs.getTargetBreakpoint(
if (miBpt != null) { context,
bs.removeCreatedTargetBreakpoint(context, miBpt); attributes,
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); new DataRequestMonitor<MIBreakpoint>(getExecutor(), drm) {
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); @Override
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); @ConfinedToDsfExecutor( "fExecutor" )
drm.setData(dmc); protected void handleSuccess() {
MIBreakpoint miBpt = getData();
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt);
drm.done(); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
return; getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
} IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
drm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
drm.done();
}
else {
GDBBreakpoints_7_4.super.addWatchpoint(context, attributes, drm);
}
}
});
}
else {
super.addWatchpoint(context, attributes, drm);
} }
super.addWatchpoint(context, attributes, drm);
} }
@Override @Override

View file

@ -51,6 +51,8 @@ import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl2; import org.eclipse.cdt.dsf.debug.service.IRunControl2;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand; import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
@ -1727,13 +1729,15 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
* @since 3.0 * @since 3.0
*/ */
@Override @Override
public void runToLine(IExecutionDMContext context, String sourceFile, public void runToLine(final IExecutionDMContext context, String sourceFile,
int lineNumber, boolean skipBreakpoints, RequestMonitor rm) { final int lineNumber, final boolean skipBreakpoints, final RequestMonitor rm) {
// Hack around a MinGW bug; see 196154 determineDebuggerPath(context, sourceFile, new ImmediateDataRequestMonitor<String>(rm) {
sourceFile = adjustDebuggerPath(sourceFile); @Override
protected void handleSuccess() {
runToLocation(context, sourceFile + ":" + Integer.toString(lineNumber), skipBreakpoints, rm); //$NON-NLS-1$ runToLocation(context, getData() + ":" + Integer.toString(lineNumber), skipBreakpoints, rm); //$NON-NLS-1$
}
});
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -1778,33 +1782,37 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
* @since 3.0 * @since 3.0
*/ */
@Override @Override
public void moveToLine(IExecutionDMContext context, String sourceFile, public void moveToLine(final IExecutionDMContext context, String sourceFile,
int lineNumber, boolean resume, RequestMonitor rm) { final int lineNumber, final boolean resume, final RequestMonitor rm) {
IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); final IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (threadExecDmc == null) { if (threadExecDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$
rm.done(); rm.done();
} }
else else
{ {
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415) determineDebuggerPath(context, sourceFile, new ImmediateDataRequestMonitor<String>(rm) {
sourceFile = adjustDebuggerPath(sourceFile); @Override
protected void handleSuccess() {
String location = sourceFile + ":" + lineNumber; //$NON-NLS-1$ String debuggerPath = getData();
if (resume)
resumeAtLocation(context, location, rm); String location = debuggerPath + ":" + lineNumber; //$NON-NLS-1$
else if (resume) {
{ resumeAtLocation(context, location, rm);
// Create the breakpoint attributes } else {
Map<String,Object> attr = new HashMap<String,Object>(); // Create the breakpoint attributes
attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); Map<String,Object> attr = new HashMap<String,Object>();
attr.put(MIBreakpoints.FILE_NAME, sourceFile); attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
attr.put(MIBreakpoints.LINE_NUMBER, lineNumber); attr.put(MIBreakpoints.FILE_NAME, debuggerPath);
attr.put(MIBreakpointDMData.IS_TEMPORARY, true); attr.put(MIBreakpoints.LINE_NUMBER, lineNumber);
attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); attr.put(MIBreakpointDMData.IS_TEMPORARY, true);
// Now do the operation attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId()));
moveToLocation(context, location, attr, rm);
} // Now do the operation
moveToLocation(context, location, attr, rm);
}
}
});
} }
} }
@ -1866,6 +1874,34 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
} }
/** /**
* Determine the path that should be sent to the debugger as per the source lookup service.
*
* @param dmc A context that can be used to obtain the sourcelookup context.
* @param hostPath The path of the file on the host, which must be converted.
* @param rm The result of the conversion.
*/
private void determineDebuggerPath(IDMContext dmc, String hostPath, final DataRequestMonitor<String> rm)
{
ISourceLookup sourceLookup = getServicesTracker().getService(ISourceLookup.class);
ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
if (sourceLookup == null || srcDmc == null) {
// Source lookup not available for given context, use the host
// path for the debugger path.
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415)
rm.done(adjustDebuggerPath(hostPath));
return;
}
sourceLookup.getDebuggerPath(srcDmc, hostPath, new DataRequestMonitor<String>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415)
rm.done(adjustDebuggerPath(getData()));
}
});
}
/**
* See bug 196154 * See bug 196154
* *
* @param path * @param path

View file

@ -549,7 +549,8 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
/** /**
* Install a platform breakpoint on the back-end. For a given context, a * Install a platform breakpoint on the back-end. For a given context, a
* platform breakpoint can resolve into multiple back-end breakpoints when * platform breakpoint can resolve into multiple back-end breakpoints when
* threads are taken into account. * threads are taken into account or if multiple breakpoints are created
* on the target using the console.
* *
* @param dmc * @param dmc
* @param breakpoint * @param breakpoint
@ -572,13 +573,6 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc); final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
assert threadsIDs != null; assert threadsIDs != null;
// Minimal validation
if (breakpointIDs.containsKey(breakpoint) || targetBPs.containsValue(breakpoint)) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_INSTALLED, null));
rm.done();
return;
}
// Ensure the breakpoint has a valid debugger source path // Ensure the breakpoint has a valid debugger source path
if (breakpoint instanceof ICLineBreakpoint if (breakpoint instanceof ICLineBreakpoint
&& !(breakpoint instanceof ICAddressBreakpoint) && !(breakpoint instanceof ICAddressBreakpoint)

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.debug.core.model.ICTracepoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint; import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.DMContexts;
@ -731,86 +732,126 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class); return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class);
} }
public MIBreakpoint getTargetBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes) { public void getTargetBreakpoint(
IBreakpointsTargetDMContext context,
Map<String, Object> attributes,
DataRequestMonitor<MIBreakpoint> rm) {
Map<Integer, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context); Map<Integer, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context);
if (map == null) if (map == null) {
return null; rm.done();
return;
}
String type = (String)attributes.get(MIBreakpoints.BREAKPOINT_TYPE); String type = (String)attributes.get(MIBreakpoints.BREAKPOINT_TYPE);
if (MIBreakpoints.BREAKPOINT.equals(type)) { if (MIBreakpoints.BREAKPOINT.equals(type)) {
return getTargetLineBreakpoint( getTargetLineBreakpoint(
context,
map.values(), map.values(),
(String)attributes.get(MIBreakpoints.FILE_NAME), (String)attributes.get(MIBreakpoints.FILE_NAME),
(Integer)attributes.get(MIBreakpoints.LINE_NUMBER), (Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
(String)attributes.get(MIBreakpoints.FUNCTION), (String)attributes.get(MIBreakpoints.FUNCTION),
(String)attributes.get(MIBreakpoints.ADDRESS), (String)attributes.get(MIBreakpoints.ADDRESS),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE), (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)); (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY),
rm);
} }
else if (MIBreakpoints.TRACEPOINT.equals(type)) { else if (MIBreakpoints.TRACEPOINT.equals(type)) {
return getTargetTracepoint( getTargetTracepoint(
context,
map.values(), map.values(),
(String)attributes.get(MIBreakpoints.FILE_NAME), (String)attributes.get(MIBreakpoints.FILE_NAME),
(Integer)attributes.get(MIBreakpoints.LINE_NUMBER), (Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
(String)attributes.get(MIBreakpoints.FUNCTION), (String)attributes.get(MIBreakpoints.FUNCTION),
(String)attributes.get(MIBreakpoints.ADDRESS), (String)attributes.get(MIBreakpoints.ADDRESS),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE), (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)); (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY),
rm);
} }
else if (MIBreakpoints.WATCHPOINT.equals(type)) { else if (MIBreakpoints.WATCHPOINT.equals(type)) {
return getTargetWatchpoint( getTargetWatchpoint(
context,
map.values(), map.values(),
(String)attributes.get(MIBreakpoints.EXPRESSION), (String)attributes.get(MIBreakpoints.EXPRESSION),
(Boolean)attributes.get(MIBreakpoints.READ), (Boolean)attributes.get(MIBreakpoints.READ),
(Boolean)attributes.get(MIBreakpoints.WRITE), (Boolean)attributes.get(MIBreakpoints.WRITE),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE), (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)); (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY),
rm);
} }
return null; else {
rm.done();
}
} }
private MIBreakpoint getTargetLineBreakpoint( private void getTargetLineBreakpoint(
IBreakpointsTargetDMContext bpTargetDMC,
Collection<MIBreakpoint> targetBreakpoints, Collection<MIBreakpoint> targetBreakpoints,
String fileName, String fileName,
Integer lineNumber, Integer lineNumber,
String function, String function,
String address, String address,
Boolean isHardware, Boolean isHardware,
Boolean isTemporary) { Boolean isTemporary,
DataRequestMonitor<MIBreakpoint> drm) {
List<MIBreakpoint> candidates = new ArrayList<MIBreakpoint>(targetBreakpoints.size());
for (MIBreakpoint miBpt : targetBreakpoints) { for (MIBreakpoint miBpt : targetBreakpoints) {
if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint() if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint()) {
&& compareBreakpointAttributes( // Filter out target breakpoints with different file names and line numbers
miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) if (fileName == null
return miBpt; || (new File(fileName).getName().equals(new File(getFileName(miBpt)).getName())
&& getLineNumber(miBpt) == lineNumber)) {
candidates.add(miBpt);
}
}
} }
return null; if (candidates.size() == 0) {
drm.done();
return;
}
findTargetLineBreakpoint(bpTargetDMC, candidates,
fileName, lineNumber, function, address, isHardware, isTemporary, drm);
} }
private MIBreakpoint getTargetTracepoint( private void getTargetTracepoint(
IBreakpointsTargetDMContext bpTargetDMC,
Collection<MIBreakpoint> targetBreakpoints, Collection<MIBreakpoint> targetBreakpoints,
String fileName, String fileName,
Integer lineNumber, Integer lineNumber,
String function, String function,
String address, String address,
Boolean isHardware, Boolean isHardware,
Boolean isTemporary) { Boolean isTemporary,
DataRequestMonitor<MIBreakpoint> rm) {
List<MIBreakpoint> candidates = new ArrayList<MIBreakpoint>(targetBreakpoints.size());
for (MIBreakpoint miBpt : targetBreakpoints) { for (MIBreakpoint miBpt : targetBreakpoints) {
if (miBpt.isTracepoint() if (miBpt.isTracepoint()) {
&& compareBreakpointAttributes( // Filter out target breakpoints with different file names and line numbers
miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) if (new File(fileName).getName().equals(new File(getFileName(miBpt)).getName())
return miBpt; && miBpt.getLine() == lineNumber) {
candidates.add(miBpt);
}
}
} }
return null; if (candidates.size() == 0) {
rm.done();
return;
}
findTargetLineBreakpoint(bpTargetDMC, candidates,
fileName, lineNumber, function, address, isHardware, isTemporary, rm);
} }
private MIBreakpoint getTargetWatchpoint( private void getTargetWatchpoint(
IBreakpointsTargetDMContext bpTargetDMC,
Collection<MIBreakpoint> targetBreakpoints, Collection<MIBreakpoint> targetBreakpoints,
String expression, String expression,
boolean readAccess, boolean readAccess,
boolean writeAccess, boolean writeAccess,
Boolean isHardware, Boolean isHardware,
Boolean isTemporary) { Boolean isTemporary,
DataRequestMonitor<MIBreakpoint> rm) {
for (MIBreakpoint miBpt : targetBreakpoints) { for (MIBreakpoint miBpt : targetBreakpoints) {
if (!miBpt.isWatchpoint()) if (!miBpt.isWatchpoint())
continue; continue;
@ -824,25 +865,92 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
continue; continue;
if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary)) if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary))
continue; continue;
return miBpt; rm.setData(miBpt);
break;
} }
return null; rm.done();
}
private void findTargetLineBreakpoint(
final IBreakpointsTargetDMContext bpTargetDMC,
final List<MIBreakpoint> candidates,
final String fileName,
final Integer lineNumber,
final String function,
final String address,
final Boolean isHardware,
final Boolean isTemporary,
final DataRequestMonitor<MIBreakpoint> drm) {
// We need to convert the debugger paths of the candidate target breakpoints
// before comparing them with the platform breakpoint's file name.
final List<MIBreakpoint> bpts = new ArrayList<MIBreakpoint>(candidates);
class FindBreakpointRM extends ImmediateDataRequestMonitor<MIBreakpoint> {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleCompleted() {
if (bpts.isEmpty()) {
drm.done();
return;
}
final MIBreakpoint bpt = bpts.remove(0);
final String debuggerPath = getFileName(bpt);
getSource(
bpTargetDMC,
debuggerPath,
new DataRequestMonitor<String>(getExecutor(), drm) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleCompleted() {
// If an error occur performing source lookup
// log it and use the debugger path.
if (!isSuccess()) {
GdbPlugin.log(getStatus());
}
if (compareBreakpointAttributes(
bpt,
isSuccess() ? getData() : debuggerPath,
fileName,
lineNumber,
function,
address,
isHardware,
isTemporary)) {
// The target breakpoint is found, we're done.
drm.setData(bpt);
drm.done();
}
else {
// Try the next candidate
new FindBreakpointRM().done();
}
}
});
}
};
// Start the search.
new FindBreakpointRM().done();
} }
private boolean compareBreakpointAttributes( private boolean compareBreakpointAttributes(
MIBreakpoint miBpt, MIBreakpoint miBpt,
String miBptFileName,
String fileName, String fileName,
Integer lineNumber, Integer lineNumber,
String function, String function,
String address, String address,
Boolean isHardware, Boolean isHardware,
Boolean isTemporary) { Boolean isTemporary) {
return compareBreakpointLocationAttributes(miBpt, fileName, lineNumber, function, address) return compareBreakpointLocationAttributes(miBpt, miBptFileName, fileName, lineNumber, function, address)
&& compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary); && compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary);
} }
private boolean compareBreakpointLocationAttributes( private boolean compareBreakpointLocationAttributes(
MIBreakpoint miBpt, MIBreakpoint miBpt,
String miBptFileName,
String fileName, String fileName,
Integer lineNumber, Integer lineNumber,
String function, String function,
@ -853,7 +961,7 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
&& (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()))) && (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString())))
return false; return false;
if (isLineBreakpoint(miBpt)) { if (isLineBreakpoint(miBpt)) {
if (fileName == null || !fileName.equals(getFileName(miBpt))) if (fileName == null || !fileName.equals(miBptFileName))
return false; return false;
if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt)) if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt))
return false; return false;

View file

@ -21,6 +21,7 @@ import java.util.Map;
import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.Immutable;
@ -40,6 +41,8 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDME
import org.eclipse.cdt.dsf.debug.service.ICachingService; import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext; import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses; import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl; import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache; import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
@ -1435,13 +1438,15 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
* @since 3.0 * @since 3.0
*/ */
@Override @Override
public void runToLine(IExecutionDMContext context, String sourceFile, public void runToLine(final IExecutionDMContext context, String sourceFile,
int lineNumber, boolean skipBreakpoints, RequestMonitor rm) { final int lineNumber, final boolean skipBreakpoints, final RequestMonitor rm) {
// Hack around a MinGW bug; see 196154 determineDebuggerPath(context, sourceFile, new ImmediateDataRequestMonitor<String>(rm) {
sourceFile = MIBreakpointsManager.adjustDebuggerPath(sourceFile); @Override
protected void handleSuccess() {
runToLocation(context, sourceFile + ":" + Integer.toString(lineNumber), skipBreakpoints, rm); //$NON-NLS-1$ runToLocation(context, getData() + ":" + Integer.toString(lineNumber), skipBreakpoints, rm); //$NON-NLS-1$
}
});
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -1487,33 +1492,37 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
* @since 3.0 * @since 3.0
*/ */
@Override @Override
public void moveToLine(IExecutionDMContext context, String sourceFile, public void moveToLine(final IExecutionDMContext context, String sourceFile,
int lineNumber, boolean resume, RequestMonitor rm) { final int lineNumber, final boolean resume, final RequestMonitor rm) {
IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); final IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (threadExecDmc == null) { if (threadExecDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$
rm.done(); rm.done();
} }
else else
{ {
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415) determineDebuggerPath(context, sourceFile, new ImmediateDataRequestMonitor<String>(rm) {
sourceFile = MIBreakpointsManager.adjustDebuggerPath(sourceFile); @Override
protected void handleSuccess() {
String location = sourceFile + ":" + lineNumber; //$NON-NLS-1$ String debuggerPath = getData();
if (resume)
resumeAtLocation(context, location, rm); String location = debuggerPath + ":" + lineNumber; //$NON-NLS-1$
else { if (resume) {
// Create the breakpoint attributes resumeAtLocation(context, location, rm);
Map<String,Object> attr = new HashMap<String,Object>(); } else {
attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); // Create the breakpoint attributes
attr.put(MIBreakpoints.FILE_NAME, sourceFile); Map<String,Object> attr = new HashMap<String,Object>();
attr.put(MIBreakpoints.LINE_NUMBER, lineNumber); attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
attr.put(MIBreakpointDMData.IS_TEMPORARY, true); attr.put(MIBreakpoints.FILE_NAME, debuggerPath);
attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); attr.put(MIBreakpoints.LINE_NUMBER, lineNumber);
attr.put(MIBreakpointDMData.IS_TEMPORARY, true);
// Now do the operation attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId()));
moveToLocation(context, location, attr, rm);
} // Now do the operation
moveToLocation(context, location, attr, rm);
}
}
});
} }
} }
@ -1578,4 +1587,32 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
// we know GDB is accepting commands // we know GDB is accepting commands
return !fTerminated && fSuspended && !fResumePending; return !fTerminated && fSuspended && !fResumePending;
} }
/**
* Determine the path that should be sent to the debugger as per the source lookup service.
*
* @param dmc A context that can be used to obtain the sourcelookup context.
* @param hostPath The path of the file on the host, which must be converted.
* @param rm The result of the conversion.
*/
private void determineDebuggerPath(IDMContext dmc, String hostPath, final DataRequestMonitor<String> rm)
{
ISourceLookup sourceLookup = getServicesTracker().getService(ISourceLookup.class);
ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
if (sourceLookup == null || srcDmc == null) {
// Source lookup not available for given context, use the host
// path for the debugger path.
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415)
rm.done(MIBreakpointsManager.adjustDebuggerPath(hostPath));
return;
}
sourceLookup.getDebuggerPath(srcDmc, hostPath, new DataRequestMonitor<String>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Hack around a MinGW bug; see 369622 (and also 196154 and 232415)
rm.done(MIBreakpointsManager.adjustDebuggerPath(getData()));
}
});
}
} }

View file

@ -381,7 +381,7 @@ abstract public class Sequence extends DsfRunnable implements Future<Object> {
} }
/* /*
* If sequence was cencelled during last step (or before the sequence * If sequence was cancelled during last step (or before the sequence
* was ever executed), start rolling back the execution. * was ever executed), start rolling back the execution.
*/ */
if (isCancelled()) { if (isCancelled()) {

View file

@ -268,8 +268,10 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe
* the model provider. * the model provider.
*/ */
fModel = factory.createModelProxy(block, context); fModel = factory.createModelProxy(block, context);
fModel.installed(null); if ( fModel != null ) {
fModel.addModelChangedListener(TraditionalRendering.this); fModel.installed(null);
fModel.addModelChangedListener(TraditionalRendering.this);
}
}}); }});
} }

View file

@ -72,9 +72,13 @@ public class SRecordExporter implements IMemoryExporter
fProperties.put(TRANSFER_START, fStartText.getText()); fProperties.put(TRANSFER_START, fStartText.getText());
fProperties.put(TRANSFER_END, fEndText.getText()); fProperties.put(TRANSFER_END, fEndText.getText());
fStartAddress = getStartAddress(); try
fEndAddress = getEndAddress(); {
fOutputFile = getFile(); fStartAddress = getStartAddress();
fEndAddress = getEndAddress();
fOutputFile = getFile();
}
catch(Exception e) {}
super.dispose(); super.dispose();
} }
@ -157,11 +161,38 @@ public class SRecordExporter implements IMemoryExporter
textValue = fProperties.get(TRANSFER_START); textValue = fProperties.get(TRANSFER_START);
fStartText.setText(textValue != null ? textValue : "0x0"); //$NON-NLS-1$ fStartText.setText(textValue != null ? textValue : "0x0"); //$NON-NLS-1$
try
{
getStartAddress();
}
catch(Exception e)
{
fStartText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
}
textValue = fProperties.get(TRANSFER_END); textValue = fProperties.get(TRANSFER_END);
fEndText.setText(textValue != null ? textValue : "0x0"); //$NON-NLS-1$ fEndText.setText(textValue != null ? textValue : "0x0"); //$NON-NLS-1$
fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString()); try
{
getEndAddress();
}
catch(Exception e)
{
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
}
try
{
fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString());
}
catch(Exception e)
{
fLengthText.setText("0");
fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
}
fileButton.addSelectionListener(new SelectionListener() { fileButton.addSelectionListener(new SelectionListener() {
@ -208,7 +239,6 @@ public class SRecordExporter implements IMemoryExporter
{ {
fStartText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); fStartText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
validate(); validate();
//fParentDialog.setValid(false);
} }
} }
@ -234,9 +264,8 @@ public class SRecordExporter implements IMemoryExporter
} }
catch(Exception ex) catch(Exception ex)
{ {
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
validate(); validate();
//fParentDialog.setValid(false);
} }
} }
@ -253,9 +282,8 @@ public class SRecordExporter implements IMemoryExporter
String endString = "0x" + getStartAddress().add(length).toString(16); //$NON-NLS-1$ String endString = "0x" + getStartAddress().add(length).toString(16); //$NON-NLS-1$
if(!fEndText.getText().equals(endString)) { if(!fEndText.getText().equals(endString)) {
if ( ! length.equals( BigInteger.ZERO ) ) { if ( ! length.equals( BigInteger.ZERO ) ) {
fLengthText.setText(endString); fEndText.setText(endString);
} }
fEndText.setText(endString);
} }
validate(); validate();
} }
@ -263,7 +291,6 @@ public class SRecordExporter implements IMemoryExporter
{ {
fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
validate(); validate();
//fParentDialog.setValid(false);
} }
} }

View file

@ -90,11 +90,15 @@ public class WinEnvironmentVariableSupplier
return value; return value;
} }
// Current support is for Windows SDK 7.1 with Visual C++ 10.0 // Current support is for Windows SDK 8.0 with Visual C++ 11.0
// Secondary support for Windows SDK 7.0 with Visual C++ 9.0 // or Windows SDK 7.1 with Visual C++ 10.0
// or Windows SDK 7.0 with Visual C++ 9.0
private static String getSDKDir() { private static String getSDKDir() {
WindowsRegistry reg = WindowsRegistry.getRegistry(); WindowsRegistry reg = WindowsRegistry.getRegistry();
String sdkDir = getSoftwareKey(reg, "Microsoft\\Microsoft SDKs\\Windows\\v7.1", "InstallationFolder"); String sdkDir = getSoftwareKey(reg, "Microsoft\\Microsoft SDKs\\Windows\\v8.0", "InstallationFolder");
if (sdkDir != null)
return sdkDir;
sdkDir = getSoftwareKey(reg, "Microsoft\\Microsoft SDKs\\Windows\\v7.1", "InstallationFolder");
if (sdkDir != null) if (sdkDir != null)
return sdkDir; return sdkDir;
return getSoftwareKey(reg, "Microsoft SDKs\\Windows\\v7.0", "InstallationFolder"); return getSoftwareKey(reg, "Microsoft SDKs\\Windows\\v7.0", "InstallationFolder");
@ -102,7 +106,10 @@ public class WinEnvironmentVariableSupplier
private static String getVCDir() { private static String getVCDir() {
WindowsRegistry reg = WindowsRegistry.getRegistry(); WindowsRegistry reg = WindowsRegistry.getRegistry();
String vcDir = getSoftwareKey(reg, "Microsoft\\VisualStudio\\SxS\\VC7", "10.0"); String vcDir = getSoftwareKey(reg, "Microsoft\\VisualStudio\\SxS\\VC7", "11.0");
if (vcDir != null)
return vcDir;
vcDir = getSoftwareKey(reg, "Microsoft\\VisualStudio\\SxS\\VC7", "10.0");
if (vcDir != null) if (vcDir != null)
return vcDir; return vcDir;
return getSoftwareKey(reg, "Microsoft\\VisualStudio\\SxS\\VC7", "9.0"); return getSoftwareKey(reg, "Microsoft\\VisualStudio\\SxS\\VC7", "9.0");
@ -151,8 +158,10 @@ public class WinEnvironmentVariableSupplier
buff = new StringBuffer(); buff = new StringBuffer();
if (vcDir != null) if (vcDir != null)
buff.append(vcDir).append("Lib;"); buff.append(vcDir).append("Lib;");
if (sdkDir != null) if (sdkDir != null) {
buff.append(sdkDir).append("Lib;"); buff.append(sdkDir).append("Lib;");
buff.append(sdkDir).append("Lib\\win8\\um\\x86;");
}
addvar(new WindowsBuildEnvironmentVariable("LIB", buff.toString(), IBuildEnvironmentVariable.ENVVAR_PREPEND)); addvar(new WindowsBuildEnvironmentVariable("LIB", buff.toString(), IBuildEnvironmentVariable.ENVVAR_PREPEND));