using cdt apis to programmatically introspect c/c++ code - eclipse · 2009-12-17 · ©wind river...

23
© 2002 IBM Corporation Confidential | Date | Other Information, if necessary © Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies. Using CDT APIs to programmatically introspect C/C++ code Markus Schorn, Wind River Systems, Inc.

Upload: others

Post on 19-Apr-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

© 2002 IBM Corporation

Confidential | Date | Other Information, if necessary

© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Using CDT APIs to programmatically introspect C/C++ code

Markus Schorn, Wind River Systems, Inc.

Page 2: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

2© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Overview

� Different Models

� C-Model

� C-Index

� Abstract Syntax Tree (AST)

� Index-based AST

� CDT’s Architecture for creating the above models

� Scalability of model creation

� Examples for using the different Models

� How to access the different models

� Questions and Suggestions

Page 3: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

3© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

C-Model

#include <math.h>

#include <stdio.h>

double circumference(double diam) {

return diam * M_PI;

}

int main(int argc, char **argv) {

double c,d;

sscanf(argv[1], "%lf", &d);

c= circumference(d);

printf("c(%f)=%f", d, c);

return 0;

}

Page 4: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

4© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

ICElements

Page 5: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

5© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

C-Model Summary

� C-Model contains information for an outline in terms of ICElements

� Include directives and macro definitions

� Non-local declarations

� File-location for each ICElement

� Notification mechanism for changes to a file in the editor

� You can register your CModelChangeListener to receive delta-information for the

ICElements of an open editor.

� Limited type information

� Types (e.g of a variable) are provided in a string representation.

� No information about references.

Page 6: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

6© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

#include <math.h>

#include <stdio.h>

double circumference(double diam) {

return diam * M_PI;

}

int main(int argc, char **argv) {

double c,d;

sscanf(argv[1], "%lf", &d);

c= circumference(d);

printf("c(%f)=%f", d, c);

return 0;

}

Index

Page 7: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

7© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Bindings and Types

Page 8: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

8© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Index Summary

� Index contains information of global interest

� Include directives and macro definitions

� Non-local declarations

� References to macros and non-local declarations

� File-location for each include, macro definition, declaration and reference

� Binding for each name

� Notification mechanism for changes to the model

� You can register your IIndexChangeListener to get informed about changes to the

index.

� Bindings and Types completely represent C/C++ entities

� Type of a variable, return type and parameters for a function.

� Fields of a composite type, owner of a field.

Page 9: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

9© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Abstract Syntax Tree#include <math.h>

double circumference(double diam) {

return diam * M_PI;

}

Page 10: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

10© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Semantics of names#include <math.h>

double circumference(double diam) {

return diam * M_PI;

}

Page 11: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

11© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Preprocessor Nodes#include <math.h>

double circumference(double diam) {

return diam * M_PI;

}

Page 12: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

12© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

AST Summary

� AST contains every little detail about the code

� Preprocessor directives, macro expansions and also comments.

� References to macro-expansions.

� Tree of nodes representing the syntax along the C/C++ grammar.

� Includes names for all declarations and references.

� File-location for each node with links to macro-expansions.

� Binding for each name

� Bindings and Types completely represent C/C++ entities

� Type of a variable, return type and parameters for a function.

� Fields of a composite type, owner of a field.

� Scopes (important for local bindings, only)

Page 13: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

13© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Index

CModel Abstract Syntax Trees Index API

Source Code

Project/Build System

Scanner

Configuration

CDT’s Parsing Architecture

Preprocessor Macro Definitions

Declarations

Indexer

Name Resolution

ASTModel Builder

CModel

Syntax Parsers

(C, C++, C99, UPC)

Preliminary AST

Page 14: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

14© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Index-based ASTdouble circumference(double diam) {

return diam * M_PI;

}

int main(int argc, char **argv) {

double c,d;

sscanf(argv[1], "%lf", &d);

c= circumference(d);

printf("c(%f)=%f", d, c);

return 0;

}

// main.c

#include <math.h>

#include <stdio.h>

Page 15: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

15© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Access to C-Model and C-Index

� C-Model: ITranslationUnit for a workspace fileIPath path= new Path("project/folder/file.c");

IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(path);

// Create translation unit for file

ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(file);

� C-Model: ITranslationUnit for file in the editorIEditorPart e= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();

// Access translation unit of the editor.

ITranslationUnit tu= (ITranslationUnit) CDTUITools.getEditorInputCElement(editor.getEditorInput());

� C-Index: IIndex for one or more projects// one project

ICProject project= CoreModel.getDefault().getCModel().getCProject("project");

IIndex index= CCorePlugin.getIndexManager().getIndex(project);

// all projects

ICProject[] allProjects= CoreModel.getDefault().getCModel().getCProjects();

index= CCorePlugin.getIndexManager().getIndex(allProjects);

Page 16: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

16© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Creating AST

� Complete AST: IASTTranslationUnit for a workspace fileITranslationUnit tu= …; // see previous slide

IASTTranslationUnit ast= tu.getAST(); // ‘getAST()’ is miss-leading, it actually creates the AST

� Index-based AST: IASTTranslationUnit for a workspace fileIIndex index= …; // see previous slide

ITranslationUnit tu= …; // see previous slide

index.acquireReadLock(); // we need a read-lock on the index

try {

ast= tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);

} finally {

index.releaseReadLock();

ast= null; // don't use the ast after releasing the read-lock

}

� AST: IASTTranslationUnit for a CodeReader (for experts, only)ILanguage lang= GPPLanguage.getDefault();

IASTTranslationUnit ast= lang.getASTTranslationUnit(reader, scannerInfo, readerFactory, index, log);

Page 17: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

17© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Accessing Shared AST

� Index-based AST: IASTTranslationUnit for file in the editor

IEditorPart e= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();

ITranslationUnit tu= (ITranslationUnit) CDTUITools.getEditorInputCElement(editor.getEditorInput());

Job job= new SharedASTJob("Job Name", tu) {

@Override

public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {

// index is locked for you, use the ast

// …

}

};

job.schedule();

Page 18: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

18© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Example #1: References in Index

void outputReferences(String functionName) throws CoreException, InterruptedException {// Access indexICProject[] allProjects= CoreModel.getDefault().getCModel().getCProjects();IIndex index= CCorePlugin.getIndexManager().getIndex(allProjects);

index.acquireReadLock(); // we need a read-lock on the indextry {

// find bindings for nameIIndexBinding[] bindings= index.findBindings(functionName.toCharArray(),

IndexFilter.ALL_DECLARED, new NullProgressMonitor());

// find references for each bindingfor (IIndexBinding b : bindings) {

if (b instanceof IFunction) {outputReferences(index, b);

}}

} finally {index.releaseReadLock();

} }

void outputReferences(IIndex index, IBinding b) throws CoreException{IIndexName[] names= index.findReferences(b);for (IIndexName n : names) {

outputReference(index, n);}

}

void outputReference(IIndex index, IIndexName n) throws CoreException {IASTFileLocation fileLoc= n.getFileLocation();System.out.println(fileLoc.getFileName() + " at offset " + fileLoc.getNodeOffset());

}

Page 19: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

19© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Example #2: Enclosing function in Index

// See previous slide

void outputReferences(String functionName) throws CoreException, InterruptedException;

// See previous slide

void outputReferences(IIndex index, IBinding b) throws CoreException;

void outputReference(IIndex index, IIndexName n) throws CoreException {

System.out.print(fileLoc.getFileName() + " at offset " + fileLoc.getNodeOffset());

// Output name of enclosing function

IIndexName within= n.getEnclosingDefinition();

if (within != null) {

IBinding enclosing= index.findBinding(within);

if (enclosing instanceof IFunction) {

System.out.print(" within " + enclosing.getName());

}

}

System.out.println();

}

Page 20: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

20© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Example #3: Get selected binding using AST

void getSelectedBinding() {

// find active editor

IEditorPart e= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();

if (!(e instanceof ITextEditor))

return;

// cursor position and translation unit

final ITextSelection sel= (ITextSelection) ((ITextEditor) e).getSelectionProvider().getSelection();

ITranslationUnit tu= (ITranslationUnit) CDTUITools.getEditorInputCElement(e.getEditorInput());

// access shared ast

Job job= new SharedASTJob("Get selected binding", tu) {

@Override

public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {

IASTNodeSelector nodeSelector= ast.getNodeSelector(null);

IASTName name= nodeSelector.findEnclosingName(sel.getOffset(), sel.getLength());

if (name != null) {

IBinding b= name.resolveBinding();

// see example #1

outputReferences(ast.getIndex(), b);

}

return Status.OK_STATUS;

}

};

job.schedule();

}

Page 21: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

21© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Example #4: Find bogus assignments in AST

void findBogusAssignments(IFile file) throws CoreException, InterruptedException {

// create translation unit and access index

ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(file);

IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject());

// lock the index for read access

index.acquireReadLock();

try {

// create index based ast

IASTTranslationUnit ast= tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);

// traverse the ast using the visitor pattern.

ast.accept(new CheckCodeVisitor());

} finally {

index.releaseReadLock();

}

}

Page 22: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

22© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Example #4 …continued

class CheckCodeVisitor extends ASTVisitor {

CheckCodeVisitor() {

shouldVisitExpressions= true;

}

public int visit(IASTExpression expression) {

if (isAssignmentExpression(expression) && isUsedAsCondition(expression)) {

System.out.println("warning ..." + expression.getFileLocation());

}

return PROCESS_CONTINUE;

}

private boolean isAssignmentExpression(IASTExpression e) {

if (e instanceof IASTBinaryExpression) {

IASTBinaryExpression binExpr= (IASTBinaryExpression) e;

return binExpr.getOperator() == IASTBinaryExpression.op_assign;

}

return false;

}

private boolean isUsedAsCondition(IASTExpression expression) {

ASTNodeProperty prop = expression.getPropertyInParent();

if (prop == IASTForStatement.CONDITION || prop == IASTIfStatement.CONDITION)

return true;

return false;

}

}

Page 23: Using CDT APIs to programmatically introspect C/C++ code - Eclipse · 2009-12-17 · ©Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies

23© Wind River Systems, released under EPL 1.0. All logos are TM of their respective companies.

Questions or Suggestions?