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,6 +77,12 @@ 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
ICdtVariableManager varManager = CCorePlugin.getDefault().getCdtVariableManager();
try {
// Substitute build/environment variables
String location = varManager.resolveValue(pathStr, "", null, cfgDescription); //$NON-NLS-1$
if (!new Path(location).isAbsolute()) {
IStringVariableManager mngr = VariablesPlugin.getDefault().getStringVariableManager(); IStringVariableManager mngr = VariablesPlugin.getDefault().getStringVariableManager();
String projectRootedPath = mngr.generateVariableExpression("workspace_loc", rc.getProject().getName()) + Path.SEPARATOR + pathStr; //$NON-NLS-1$ 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()); ICLanguageSettingEntry projectRootedEntry = (ICLanguageSettingEntry) CDataUtil.createEntry(kind, projectRootedPath, projectRootedPath, null, entry.getFlags());
@ -80,6 +90,12 @@ public class MBSLanguageSettingsProvider extends AbstractExecutableExtensionBase
list.add(projectRootedEntry); list.add(projectRootedEntry);
} }
} }
} catch (CdtVariableException e) {
// Swallow exceptions but also log them
ManagedBuilderCorePlugin.log(e);
}
}
} }
if (! list.contains(entry)) { if (! list.contains(entry)) {
list.add(entry); list.add(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();
if (LT(1) != IToken.tEOC) {
consume(IToken.tGT, IToken.tGT_in_SHIFTR); 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;
try {
if (containsDependentType(fnArgs)) if (containsDependentType(fnArgs))
return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)};
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.createForSample(template); inst= CPPDeferredFunction.createForCandidates(functions);
done= true; done= true;
} }
checkedForDependentType= true; checkedForDependentType= true;
} catch (DOMException e) {
return functions;
}
} }
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;
if (originalArguments != null)
arguments = instantiateArguments(originalArguments, tpMap, packOffset, within, point); 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':
if (fOptions.fSupportRawStringLiterals) {
markPhase3(); markPhase3();
if (nextCharPhase3() == '"') { if (nextCharPhase3() == '"') {
nextCharPhase3(); nextCharPhase3();
return rawStringLiteral(start, 3, IToken.tLSTRING); 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':
if (fOptions.fSupportRawStringLiterals) {
markPhase3(); markPhase3();
if (nextCharPhase3() == '"') { if (nextCharPhase3() == '"') {
nextCharPhase3(); nextCharPhase3();
return rawStringLiteral(start, 3, c == 'u' ? IToken.tUTF16STRING : IToken.tUTF32STRING); 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

@ -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

@ -271,7 +271,7 @@ 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) {
@ -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;
@ -514,7 +522,7 @@ public class MacroExpander {
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;
} }
@ -530,7 +538,7 @@ public class MacroExpander {
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++;
@ -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,6 +978,12 @@ 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;

View file

@ -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

@ -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;

View file

@ -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,9 +27,9 @@ 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;
} }
@ -40,13 +41,13 @@ class TokenList {
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) {
@ -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,16 +124,17 @@ 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() {

View file

@ -147,7 +147,6 @@ public class TokenUtil {
} }
} }
/** /**
* 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
@ -159,5 +158,4 @@ public class TokenUtil {
} 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);
final int continuationIndentation = preferences.continuation_indentation; options.fSeparatorToken = Token.tCOMMA;
Alignment listAlignment = scribe.createAlignment( options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_invocation;
Alignment.MACRO_ARGUMENTS, options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_invocation;
preferences.alignment_for_arguments_in_method_invocation, options.fSpaceBetweenEmptyParen= preferences.insert_space_between_empty_parens_in_method_invocation;
Alignment.R_OUTERMOST, options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_method_invocation_arguments;
binding.getParameterList().length, options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_method_invocation_arguments;
getCurrentPosition(), options.fTieBreakRule = Alignment.R_OUTERMOST;
continuationIndentation, fInsideMacroArguments = true;
false);
scribe.enterAlignment(listAlignment);
boolean ok = false;
do {
try { try {
int fragment = 0; formatList(arguments, options, true, false, scribe.takeTailFormatter());
scribe.alignFragment(listAlignment, fragment); } finally {
fInsideMacroArguments = false;
}
}
/**
* Scans macro expansion arguments starting from the current position and returns a list of
* arguments where each argument is represented either by a {@link IASTNode} or, if not
* possible, by a {@link TokenRange}.
*/
private List<Object> getMacroArguments(int expectedNumberOfArguments) {
List<TokenRange> argumentRanges = new ArrayList<TokenRange>(expectedNumberOfArguments);
TokenRange currentArgument = null;
localScanner.resetTo(getCurrentPosition(), scribe.scannerEndPosition);
localScanner.getNextToken(); // Skip the opening parenthesis.
int parenLevel = 0; int parenLevel = 0;
boolean done = false; int token;
while (!done) { while ((token = localScanner.getNextToken()) != Token.tBADCHAR) {
boolean hasWhitespace= scribe.printComment(); int tokenOffset = localScanner.getCurrentTokenStartPosition();
int token = peekNextToken(); if (parenLevel == 0 && (token == Token.tCOMMA || token == Token.tRPAREN)) {
if (currentArgument != null) {
argumentRanges.add(currentArgument);
currentArgument = null;
} else {
argumentRanges.add(new TokenRange(tokenOffset, tokenOffset));
}
if (token == Token.tRPAREN)
break;
} else {
int tokenEndOffset = localScanner.getCurrentPosition();
if (currentArgument == null) {
currentArgument = new TokenRange(tokenOffset, tokenEndOffset);
} else {
currentArgument.endOffset = tokenEndOffset;
}
switch (token) { switch (token) {
case Token.tLPAREN: case Token.tLPAREN:
++parenLevel; ++parenLevel;
scribe.printNextToken(token, hasWhitespace);
break; break;
case Token.tRPAREN: case Token.tRPAREN:
if (parenLevel > 0) { if (parenLevel > 0)
--parenLevel; --parenLevel;
scribe.printNextToken(token, hasWhitespace); break;
}
}
}
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 { } else {
if (preferences.insert_space_before_closing_paren_in_method_invocation) { arguments.add(argument);
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; return arguments;
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.tSEMI) {
scribe.printNextToken(token);
scribe.startNewLine();
}
ok = true;
} catch (AlignmentException e) {
scribe.redoAlignment(e);
}
} while (!ok);
scribe.exitAlignment(listAlignment, true);
} }
@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) {
if (element instanceof ICPPASTConstructorChainInitializer) {
// Constructor chain initializer is a special case. // Constructor chain initializer is a special case.
visit((ICPPASTConstructorChainInitializer) node); visit((ICPPASTConstructorChainInitializer) element);
} else { } else {
node.accept(this); ((IASTNode) element).accept(this);
}
} else {
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,6 +3885,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
if (currentOffset > nodeEndOffset) { if (currentOffset > nodeEndOffset) {
return; return;
} }
if (!fInsideMacroArguments) {
IASTNodeLocation[] locations= node.getNodeLocations(); IASTNodeLocation[] locations= node.getNodeLocations();
for (int i= 0; i < locations.length; i++) { for (int i= 0; i < locations.length; i++) {
IASTNodeLocation nodeLocation= locations[i]; IASTNodeLocation nodeLocation= locations[i];
@ -3873,6 +3904,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
} }
} }
} }
}
private int getNextTokenOffset() { private int getNextTokenOffset() {
localScanner.resetTo(getCurrentPosition(), scribe.scannerEndPosition); localScanner.resetTo(getCurrentPosition(), scribe.scannerEndPosition);
@ -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;

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
@ -97,7 +97,7 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
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,11 +116,13 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
long endTime= System.currentTimeMillis(); long endTime= System.currentTimeMillis();
assertTrue(results != null); assertTrue(results != null);
if (filterResults) {
if (isTemplate) { if (isTemplate) {
results= filterResultsKeepTemplates(results); results= filterResultsKeepTemplates(results);
} else { } else {
results= filterResults(results, isCode); results= filterResults(results, isCode);
} }
}
String[] resultStrings= toStringArray(results, compareType); String[] resultStrings= toStringArray(results, compareType);
Arrays.sort(expected); Arrays.sort(expected);
Arrays.sort(resultStrings); Arrays.sort(resultStrings);
@ -161,6 +163,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,6 +1081,7 @@ public class LanguageSettingsProviderTab extends AbstractCPropertyTab {
return; return;
ICConfigurationDescription cfgDescription = getConfigurationDescription(); ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription != null) {
String cfgId = cfgDescription.getId(); String cfgId = cfgDescription.getId();
if (!initialProvidersByCfg.containsKey(cfgId)) { if (!initialProvidersByCfg.containsKey(cfgId)) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
@ -1088,6 +1089,7 @@ public class LanguageSettingsProviderTab extends AbstractCPropertyTab {
initialProvidersByCfg.put(cfgId, initialProviders); initialProvidersByCfg.put(cfgId, initialProviders);
} }
} }
}
if (rcDes!=null) { if (rcDes!=null) {
if (page.isMultiCfg()) { if (page.isMultiCfg()) {

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,73 +170,118 @@ 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(
context,
attributes,
new DataRequestMonitor<MIBreakpoint>(getExecutor(), finalRm) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleSuccess() {
MIBreakpoint miBpt = getData();
if (miBpt != null) { if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt); bs.removeCreatedTargetBreakpoint(context, miBpt);
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
finalRm.setData(dmc); finalRm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
finalRm.done(); finalRm.done();
return; }
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(
context,
attributes,
new DataRequestMonitor<MIBreakpoint>(getExecutor(), drm) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleSuccess() {
MIBreakpoint miBpt = getData();
if (miBpt != null) { if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt); bs.removeCreatedTargetBreakpoint(context, miBpt);
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
drm.setData(dmc); drm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
drm.done(); drm.done();
return; }
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(
context,
attributes,
new DataRequestMonitor<MIBreakpoint>(getExecutor(), drm) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleSuccess() {
MIBreakpoint miBpt = getData();
if (miBpt != null) { if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt); bs.removeCreatedTargetBreakpoint(context, miBpt);
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber()); IBreakpointDMContext dmc =
new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber());
drm.setData(dmc); drm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
drm.done(); drm.done();
return; }
else {
GDBBreakpoints_7_4.super.addWatchpoint(context, attributes, drm);
} }
} }
});
}
else {
super.addWatchpoint(context, attributes, drm); super.addWatchpoint(context, attributes, drm);
} }
}
@Override @Override
protected void deleteBreakpointFromTarget(IBreakpointsTargetDMContext context, int reference, RequestMonitor finalRm) { protected void deleteBreakpointFromTarget(IBreakpointsTargetDMContext context, int reference, RequestMonitor finalRm) {

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,34 +1782,38 @@ 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 debuggerPath = getData();
String location = sourceFile + ":" + lineNumber; //$NON-NLS-1$ String location = debuggerPath + ":" + lineNumber; //$NON-NLS-1$
if (resume) if (resume) {
resumeAtLocation(context, location, rm); resumeAtLocation(context, location, rm);
else } else {
{
// Create the breakpoint attributes // Create the breakpoint attributes
Map<String,Object> attr = new HashMap<String,Object>(); Map<String,Object> attr = new HashMap<String,Object>();
attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
attr.put(MIBreakpoints.FILE_NAME, sourceFile); attr.put(MIBreakpoints.FILE_NAME, debuggerPath);
attr.put(MIBreakpoints.LINE_NUMBER, lineNumber); attr.put(MIBreakpoints.LINE_NUMBER, lineNumber);
attr.put(MIBreakpointDMData.IS_TEMPORARY, true); attr.put(MIBreakpointDMData.IS_TEMPORARY, true);
attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId()));
// Now do the operation // Now do the operation
moveToLocation(context, location, attr, rm); moveToLocation(context, location, attr, rm);
} }
} }
});
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -1865,6 +1873,34 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
return true; return true;
} }
/**
* 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
* *

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;
} }
private MIBreakpoint getTargetTracepoint( findTargetLineBreakpoint(bpTargetDMC, candidates,
fileName, lineNumber, function, address, isHardware, isTemporary, drm);
}
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;
} }
private MIBreakpoint getTargetWatchpoint( findTargetLineBreakpoint(bpTargetDMC, candidates,
fileName, lineNumber, function, address, isHardware, isTemporary, rm);
}
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,26 +1492,28 @@ 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 debuggerPath = getData();
String location = sourceFile + ":" + lineNumber; //$NON-NLS-1$ String location = debuggerPath + ":" + lineNumber; //$NON-NLS-1$
if (resume) if (resume) {
resumeAtLocation(context, location, rm); resumeAtLocation(context, location, rm);
else { } else {
// Create the breakpoint attributes // Create the breakpoint attributes
Map<String,Object> attr = new HashMap<String,Object>(); Map<String,Object> attr = new HashMap<String,Object>();
attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
attr.put(MIBreakpoints.FILE_NAME, sourceFile); attr.put(MIBreakpoints.FILE_NAME, debuggerPath);
attr.put(MIBreakpoints.LINE_NUMBER, lineNumber); attr.put(MIBreakpoints.LINE_NUMBER, lineNumber);
attr.put(MIBreakpointDMData.IS_TEMPORARY, true); attr.put(MIBreakpointDMData.IS_TEMPORARY, true);
attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId()));
@ -1515,6 +1522,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
moveToLocation(context, location, attr, rm); moveToLocation(context, location, attr, rm);
} }
} }
});
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -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);
if ( fModel != null ) {
fModel.installed(null); fModel.installed(null);
fModel.addModelChangedListener(TraditionalRendering.this); 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());
try
{
fStartAddress = getStartAddress(); fStartAddress = getStartAddress();
fEndAddress = getEndAddress(); fEndAddress = getEndAddress();
fOutputFile = getFile(); fOutputFile = getFile();
}
catch(Exception e) {}
super.dispose(); super.dispose();
} }
@ -158,10 +162,37 @@ 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$
try
{
getEndAddress();
}
catch(Exception e)
{
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
}
try
{
fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString()); 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);
} }
} }
@ -236,7 +266,6 @@ public class SRecordExporter implements IMemoryExporter
{ {
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
validate(); validate();
//fParentDialog.setValid(false);
} }
} }
@ -253,17 +282,15 @@ 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();
} }
catch(Exception ex) catch(Exception ex)
{ {
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));