1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 45203. Properly generate include statements for external macro

definitions.
This commit is contained in:
Sergey Prigogin 2013-07-31 18:15:41 -07:00
parent 601790eebf
commit 2ac00ea300
8 changed files with 129 additions and 48 deletions

View file

@ -14,6 +14,7 @@ import java.io.IOException;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -53,10 +54,11 @@ import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
public class LocationMapTests extends BaseTestCase {
public class Loc implements IASTFileLocation {
public class Loc implements IASTFileLocation, IName {
private String fFile;
private int fOffset;
private int fEndOffset;
public Loc(String file, int offset, int endOffset) {
fFile= file;
fOffset= offset;
@ -72,7 +74,7 @@ public class LocationMapTests extends BaseTestCase {
}
@Override
public int getNodeLength() {
return fEndOffset-fOffset;
return fEndOffset - fOffset;
}
@Override
public int getNodeOffset() {
@ -90,6 +92,30 @@ public class LocationMapTests extends BaseTestCase {
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
@Override
public char[] getSimpleID() {
return new char[0];
}
@Override
public char[] toCharArray() {
return getSimpleID();
}
@Override
public boolean isDeclaration() {
return false;
}
@Override
public boolean isReference() {
return false;
}
@Override
public boolean isDefinition() {
return true;
}
@Override
public IASTFileLocation getFileLocation() {
return this;
}
}
private static final String FN = "filename";

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -23,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.core.runtime.IAdaptable;
/**
* Models IASTNames as needed for the preprocessor statements and macro expansions.
@ -150,13 +152,13 @@ class ASTPreprocessorDefinition extends ASTPreprocessorName {
}
}
class ASTBuiltinName extends ASTPreprocessorDefinition {
private final IASTFileLocation fFileLocation;
class ASTBuiltinName extends ASTPreprocessorDefinition implements IAdaptable {
private final IName fOriginalDefinition;
public ASTBuiltinName(IASTNode parent, ASTNodeProperty property, IASTFileLocation floc,
public ASTBuiltinName(IASTNode parent, ASTNodeProperty property, IName originalDefinition,
char[] name, IBinding binding) {
super(parent, property, -1, -1, name, binding);
fFileLocation= floc;
fOriginalDefinition= originalDefinition;
}
@Override
@ -166,31 +168,40 @@ class ASTBuiltinName extends ASTPreprocessorDefinition {
@Override
public String getContainingFilename() {
if (fFileLocation == null) {
return ""; //$NON-NLS-1$
}
return fFileLocation.getFileName();
IASTFileLocation fileLocation = getFileLocation();
return fileLocation == null ? "" : fileLocation.getFileName(); //$NON-NLS-1$
}
@Override
public IASTFileLocation getFileLocation() {
return fFileLocation;
return fOriginalDefinition == null ? null : fOriginalDefinition.getFileLocation();
}
@Override
public IASTNodeLocation[] getNodeLocations() {
if (fFileLocation == null) {
IASTFileLocation fileLocation = getFileLocation();
if (fileLocation == null) {
return IASTNodeLocation.EMPTY_ARRAY;
}
return new IASTNodeLocation[] { fFileLocation };
return new IASTNodeLocation[] { fileLocation };
}
@Override
public String getRawSignature() {
if (fFileLocation == null) {
return ""; //$NON-NLS-1$
IASTFileLocation fileLocation = getFileLocation();
return fileLocation == null ? "" : toString(); //$NON-NLS-1$
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(ASTBuiltinName.class)) {
return this;
}
return toString();
if (adapter.isAssignableFrom(fOriginalDefinition.getClass())) {
return fOriginalDefinition;
}
return null;
}
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -502,9 +503,9 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor
* Constructor for built-in macros
* @param expansionOffset
*/
public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, IASTFileLocation floc, int expansionOffset) {
public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, IName originalDefinition, int expansionOffset) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, -1, -1);
fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, floc, macro.getNameCharArray(), macro);
fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, originalDefinition, macro.getNameCharArray(), macro);
fExpansionNumber= -1;
fExpansionOffset= expansionOffset;
}
@ -605,8 +606,8 @@ class ASTFunctionStyleMacroDefinition extends ASTMacroDefinition implements IAST
* Constructor for builtins
*/
public ASTFunctionStyleMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro,
IASTFileLocation nameLoc, int expansionOffset) {
super(parent, macro, nameLoc, expansionOffset);
IName originalDefinition, int expansionOffset) {
super(parent, macro, originalDefinition, expansionOffset);
}
@Override

View file

@ -23,7 +23,6 @@ import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
@ -1200,8 +1199,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
} else {
PreprocessorMacro result= MacroDefinitionParser.parseMacroDefinition(
macro.getNameCharArray(), macro.getParameterList(), expansionImage);
final IASTFileLocation loc= macro.getFileLocation();
fLocationMap.registerMacroFromIndex(result, loc, -1);
fLocationMap.registerMacroFromIndex(result, macro.getDefinition(), -1);
fMacroDictionary.put(result.getNameCharArray(), result);
}
} catch (Exception e) {

View file

@ -16,6 +16,7 @@ import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
@ -78,18 +79,18 @@ public class LocationMap implements ILocationResolver {
registerPredefinedMacro(macro, null, -1);
}
public void registerMacroFromIndex(IMacroBinding macro, IASTFileLocation nameLocation, int expansionOffset) {
registerPredefinedMacro(macro, nameLocation, expansionOffset);
public void registerMacroFromIndex(IMacroBinding macro, IName originalDefinition, int expansionOffset) {
registerPredefinedMacro(macro, originalDefinition, expansionOffset);
}
private void registerPredefinedMacro(IMacroBinding macro, IASTFileLocation nameloc, int expansionOffset) {
ASTMacroDefinition astmacro;
private void registerPredefinedMacro(IMacroBinding macro, IName originalDefinition, int expansionOffset) {
ASTMacroDefinition astMacro;
if (macro.isFunctionStyle()) {
astmacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macro, nameloc, expansionOffset);
astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macro, originalDefinition, expansionOffset);
} else {
astmacro= new ASTMacroDefinition(fTranslationUnit, macro, nameloc, expansionOffset);
astMacro= new ASTMacroDefinition(fTranslationUnit, macro, originalDefinition, expansionOffset);
}
fBuiltinMacros.add(astmacro);
fBuiltinMacros.add(astMacro);
}
/**

View file

@ -14,6 +14,7 @@ import java.util.List;
import junit.framework.Test;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MultiTextEdit;
@ -24,6 +25,7 @@ import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition;
/**
* Tests for {@link IncludeOrganizer}.
@ -45,13 +47,14 @@ public class IncludeOrganizerTest extends IncludesTestBase {
@Override
protected void resetPreferences() {
super.resetPreferences();
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
IPreferenceStore preferenceStore = getPreferenceStore();
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
}
private void assertExpectedResults() throws Exception {
@ -330,4 +333,28 @@ public class IncludeOrganizerTest extends IncludesTestBase {
public void testHeaderExport() throws Exception {
assertExpectedResults();
}
//h1.h
//#define M2(t, p) t p
//h2.h
//#include "h1.h"
//#define M1(x, y) M2(int, x) = y
//h3.h
//#include "h2.h"
//source.cpp
//#include "h3.h"
//M1(a, 1);
//====================
//#include "h2.h"
//
//M1(a, 1);
public void testMacro() throws Exception {
IPreferenceStore preferenceStore = getPreferenceStore();
preferenceStore.setValue(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION,
UnusedStatementDisposition.REMOVE.toString());
assertExpectedResults();
}
}

View file

@ -55,6 +55,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
@ -1011,8 +1012,9 @@ public class BindingClassifier {
@Override
public int visit(IASTTranslationUnit tu) {
for (IASTPreprocessorMacroExpansion macroExpansion : tu.getMacroExpansions()) {
IBinding binding = macroExpansion.getMacroReference().getBinding();
defineBinding(binding);
IASTPreprocessorMacroDefinition macroDefinition = macroExpansion.getMacroDefinition();
IASTName name = macroDefinition.getName();
defineBinding(name.getBinding());
}
return PROCESS_CONTINUE;
}

View file

@ -28,6 +28,7 @@ import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
@ -48,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement;
@ -58,6 +60,7 @@ import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
@ -83,6 +86,7 @@ import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
import org.eclipse.cdt.internal.core.parser.scanner.CharArray;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
import org.eclipse.cdt.internal.core.parser.scanner.IncludeGuardDetection;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
@ -203,7 +207,7 @@ public class IncludeOrganizer {
// bindings which have to be defined.
IIndexFileSet reachableHeaders = ast.getIndexFileSet();
List<InclusionRequest> requests = createInclusionRequests(bindingsToDefine, reachableHeaders);
List<InclusionRequest> requests = createInclusionRequests(ast, bindingsToDefine, reachableHeaders);
processInclusionRequests(requests, headerSubstitutor);
// Use a map instead of a set to be able to retrieve existing elements using equal elements.
@ -365,7 +369,7 @@ public class IncludeOrganizer {
Set<IBinding> bindingsToDefine) throws CoreException {
IIndexFileSet reachableHeaders = ast.getIndexFileSet();
Set<IBinding> bindings =
removeBindingsDefinedInIncludedHeaders(classifier.getBindingsToDeclare(), reachableHeaders);
removeBindingsDefinedInIncludedHeaders(ast, classifier.getBindingsToDeclare(), reachableHeaders);
for (IBinding binding : bindings) {
// Create the text of the forward declaration of this binding.
StringBuilder declarationText = new StringBuilder();
@ -573,7 +577,7 @@ public class IncludeOrganizer {
}
}
}
if (includeOffset <= 0) {
if (includeOffset < 0) {
if (includeGuardEndOffset >= 0) {
includeOffset = skipToNextLine(includeGuardEndOffset);
} else {
@ -829,11 +833,11 @@ public class IncludeOrganizer {
return fContext.getPreferences().includeStyles.get(includeKind);
}
private Set<IBinding> removeBindingsDefinedInIncludedHeaders(Set<IBinding> bindings,
IIndexFileSet reachableHeaders) throws CoreException {
private Set<IBinding> removeBindingsDefinedInIncludedHeaders(IASTTranslationUnit ast,
Set<IBinding> bindings, IIndexFileSet reachableHeaders) throws CoreException {
Set<IBinding> filteredBindings = new HashSet<IBinding>(bindings);
List<InclusionRequest> requests = createInclusionRequests(bindings, reachableHeaders);
List<InclusionRequest> requests = createInclusionRequests(ast, bindings, reachableHeaders);
Set<IPath> allIncludedHeaders = new HashSet<IPath>();
allIncludedHeaders.addAll(fContext.getHeadersAlreadyIncluded());
allIncludedHeaders.addAll(fContext.getHeadersToInclude());
@ -1015,14 +1019,25 @@ public class IncludeOrganizer {
return false;
}
private List<InclusionRequest> createInclusionRequests(Set<IBinding> bindingsToDefine,
IIndexFileSet reachableHeaders) throws CoreException {
private List<InclusionRequest> createInclusionRequests(IASTTranslationUnit ast,
Set<IBinding> bindingsToDefine, IIndexFileSet reachableHeaders) throws CoreException {
List<InclusionRequest> requests = new ArrayList<InclusionRequest>(bindingsToDefine.size());
IIndex index = fContext.getIndex();
binding_loop: for (IBinding binding : bindingsToDefine) {
IIndexName[] indexNames;
if (binding instanceof IFunction) {
if (binding instanceof IMacroBinding) {
indexNames = IIndexName.EMPTY_ARRAY;
ILocationResolver resolver = (ILocationResolver) ast.getAdapter(ILocationResolver.class);
IASTName[] declarations = resolver.getDeclarations((IMacroBinding) binding);
for (IASTName name : declarations) {
if (name instanceof IAdaptable) {
IIndexName indexName = (IIndexName) ((IAdaptable) name).getAdapter(IIndexName.class);
indexNames = Arrays.copyOf(indexNames, indexNames.length + 1);
indexNames[indexNames.length - 1] = indexName;
}
}
} else if (binding instanceof IFunction) {
// For functions we need to include the declaration.
indexNames = index.findDeclarations(binding);
} else {