1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
|
// This file is part of the AspectC++ compiler 'ac++'.
// Copyright (C) 1999-2003 The 'ac++' developers (see aspectc.org)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA
#ifndef __ClangModelBuilder_h__
#define __ClangModelBuilder_h__
#include "ACModel/Elements.h"
#include "ACToken.h"
#include "ACProject.h"
#include "ClangToken.h"
#include "TransformInfo.h"
#include "ACErrorStream.h"
#include "ClangAnnotation.h"
#include "ClangFlowAnalysis.h"
namespace Puma {
class VerboseMgr;
}
namespace clang {
class Decl;
class DeclContext;
class Stmt;
class CallExpr;
class FunctionDecl;
class NamespaceDecl;
class RecordDecl;
class SourceLocation;
class QualType;
}
namespace llvm {
class StringRef;
}
class ACConfig;
// FIXME: needs to be ported to clang
//struct AccessInfo {
// Puma::CAttributeInfo *_info;
// Puma::CTree *_tree;
// AccessInfo () {}
// AccessInfo (Puma::CAttributeInfo *info, Puma::CTree *tree) :
// _info (info), _tree (tree) {}
//
//};
//
class ClangModelBuilder : public ProjectModel {
Puma::VerboseMgr &_vm;
ACErrorStream &_err;
ACConfig &_conf;
ACProject &_project;
ACM_TUnit *_tunit_file;
ClangFlowAnalysis _flow_analysis;
AnnotationMap _annotation_map;
Annotation *_annotation_context;
public:
// map needed to check if a file is already known
typedef map<std::string, ACM_File*> FileMap;
typedef FileMap::value_type FileMapPair;
FileMap _file_map;
FileMap &file_map() { return _file_map; }
// config is needed for decisions in ASTConsumer
ACConfig &conf() { return _conf; }
const AnnotationMap &annotation_map() const { return _annotation_map; }
AnnotationMap &annotation_map() { return _annotation_map; }
Annotation *&annotation_context () { return _annotation_context; }
private:
int _tunit_len;
// FIXME: needs to be ported to clang
// TODO: temporary solution
// list<AccessInfo> _access_infos;
int _time;
public:
void advice_infos (ACM_Aspect *jpl_aspect);
// determine a model element filename for a unit
string model_filename (const char *fname);
// get the modification time of a file (UNIX Epoch value)
long modification_time (const string &name);
ClangModelBuilder (Puma::VerboseMgr &vm, ACErrorStream &err, ACConfig &conf, ACProject &project) :
_vm (vm), _err (err), _conf (conf), _project(project), _annotation_context (0) {}
ACProject &get_project () const { return _project; }
void setup_phase1 (const string &tunit_name, int tunit_len);
bool is_valid_model_class (clang::RecordDecl *ci) const;
bool is_intro_target (clang::Decl *ci) const;
bool is_valid_model_function (clang::FunctionDecl *fi) const;
bool is_valid_model_variable( clang::DeclaratorDecl *vi ) const;
bool is_valid_model_namespace (clang::NamespaceDecl *ni) const;
bool is_valid_model_type( const clang::QualType& ) const;
bool inside_template (clang::DeclContext *scope) const;
static bool inside_template_instance (clang::DeclContext *scope);
// create a type in the join point model from a Puma node
TU_Type *register_type (clang::QualType ti);
// create a (pointcut) argument in the join point model from a Puma node
TU_Arg *register_arg (clang::QualType ti, llvm::StringRef name);
// get the translation unit as a model object
ACM_TUnit *tunit_file () const { return _tunit_file; }
// create a named pointcut in the join point model (phase 1)
ACM_Pointcut *register_pointcut1 (ACM_Name *parent, const std::string &name,
bool is_virtual, const std::string& expr);
bool overrides_virtual_pointcut (ACM_Name *parent, const string &name); // helper function
// create an attribute in the join point model (phase 1)
TU_Attribute *register_attrdecl1(ACM_Namespace *parent, const std::string &name);
// find an attribute declaration
TU_Attribute *find_attrdecl (const std::vector<std::string> &qual_name);
// create a named pointcut in the join point model from a Puma node
TU_Pointcut *register_pointcut (clang::FunctionDecl *fi, ACM_Name *parent);
// create an attribute in the join point model from an AST node
TU_Attribute *register_attrdecl (clang::FunctionDecl *fi, ACM_Name *parent = 0);
// register an annotation, e.g. [[ns::foo(42)]], which is seen by the clang parser
// as a function call in an introduced code fragment
// The analysis results (parameters, etc.) are store in *_annotation_context, which
// is set in advance by the introducer, which hands-over the generated source code
// to the parser.
void register_annotation (clang::CallExpr *expr);
// create a function in the join point model from a Puma node
TU_Function *register_function (clang::FunctionDecl *fi,
ACM_Name *parent = 0);
// create a global variable or member variable in the join point model
TU_Variable *register_variable( clang::DeclaratorDecl *oi, ACM_Name *parent = 0 );
// create a statement node (needed when a statement has been annotated)
ACM_Statement *register_statement ( clang::AttributedStmt *as, ACM_Name *parent);
// create a class slice in the join point model (phase 1)
ACM_ClassSlice *register_class_slice (ACM_Name *scope, string name, bool is_struct);
// create a class in the join point model (phase 1)
ACM_Class *register_class1 (ACM_Name *scope, std::string name, bool in_project = true);
//create a reference to the Attribute in the join point model
// TU_Attribute *register_attribute(clang::RecordDecl *ci, ACM_Name *parent = 0, bool set_source = true);
// create a class in the join point model from a Puma node
TU_Class *register_class (clang::RecordDecl *ci, ACM_Name *parent = 0, bool set_source = true);
// register the implicitly defined constructor/destructor for a class or aspect
void register_constructor_and_destructor (clang::RecordDecl *ci, ACM_Class *elem);
// create an aspect in the join point model (phase 1)
ACM_Aspect *register_aspect1 (ACM_Name *scope, std::string name,
bool in_project = true);
// create an aspect in the join point model from a Puma node
TU_Aspect *register_aspect (clang::RecordDecl *ci, ACM_Name *parent = 0);
// create a Namespace in the join point model (phase 1)
ACM_Namespace *register_namespace1 (ACM_Name *scope, std::string name,
bool in_project = true);
// create a Namespace in the join point model from a Puma node (phase 2)
TU_Namespace *register_namespace (clang::NamespaceDecl *ni,
ACM_Name *parent = 0);
// classes to hold parameters when registering access joinpoints
struct JoinpointContext {
ACM_Any *parent;
clang::Decl *parent_decl;
unsigned local_id;
};
template<typename ElementType, typename DeclType> struct EntityAccessInfo {
ElementType *element;
DeclType *decl;
clang::Expr *tree_node;
clang::Expr *ref_node;
};
typedef EntityAccessInfo<ACM_Variable, clang::DeclaratorDecl> VarAccessInfo;
// This method creates a new built-in operator-"pseudo"-function and a call
// of this function and registers both in the AspectC++-join-point-model.
TU_Builtin* register_builtin_operator_call(clang::Expr*, clang::DeclaratorDecl*, int,
ACM_Statement *stmt = 0);
// create a new call join point in the join point model
ACM_Access *register_call (clang::FunctionDecl *called, clang::CallExpr
*call_node, clang::DeclaratorDecl *caller,
int local_id, ACM_Statement *stmt = 0);
// create a new get join point
ACM_Access *register_get( VarAccessInfo &var, JoinpointContext& context, TU_Builtin *var_src = 0 );
// create a new set join point
ACM_Access *register_set( VarAccessInfo &var, JoinpointContext& context, TU_Builtin *var_src = 0 );
// create a new ref join point
TU_Ref *register_ref( VarAccessInfo &var, JoinpointContext& context, TU_Builtin *var_src = 0 );
// fill common information in Access node
template<class NODE> void fillAccessNode( NODE *new_elem, VarAccessInfo &var, JoinpointContext& context, TU_Builtin *var_src );
// fill common information in Access nodes using ref only
template<class NODE> void fillRefAccessNode( NODE *new_elem, VarAccessInfo &var, JoinpointContext& context );
// create a new execution join point
TU_Method *register_execution (ACM_Function *ef);
// create a new construction join point
TU_Construction *register_construction (ACM_Function *cf);
// create a new construction join point
TU_Destruction *register_destruction (ACM_Function *df);
// TODO: temporary solution for dac++
// FIXME: needs to be ported to clang
// void register_attr_access (Puma::CAttributeInfo *attr, Puma::CTree *node);
// register the scope of a given element
ACM_Name *register_scope( clang::DeclaratorDecl *obj );
ACM_Name *register_scope (clang::DeclContext *obj, bool parent = true);
// extended types...
// factory methods that remember all objects of this model
virtual TU_CodeAdvice *newCodeAdvice() { return remember (new TU_CodeAdvice, JPTI_CodeAdvice); }
virtual TU_Type *newType() { return remember (new TU_Type, JPTI_Type); }
virtual TU_Arg *newArg() { return remember (new TU_Arg, JPTI_Arg); }
virtual TU_Namespace *newNamespace() { return remember (new TU_Namespace, JPTI_Namespace); }
virtual TU_Variable *newVariable() { return remember (new TU_Variable, JPTI_Variable); }
virtual TU_Function *newFunction() { return remember (new TU_Function, JPTI_Function); }
virtual TU_Class *newClass() { return remember (new TU_Class, JPTI_Class); }
virtual TU_ClassSlice *newClassSlice() { return remember (new TU_ClassSlice, JPTI_ClassSlice); }
virtual TU_MethodCall *newCall() { return remember (new TU_MethodCall, JPTI_Call); }
virtual TU_Builtin *newBuiltin() { return remember (new TU_Builtin, JPTI_Builtin); }
virtual TU_Get *newGet() { return remember( new TU_Get(), JPTI_Get ); }
virtual TU_Set *newSet() { return remember( new TU_Set(), JPTI_Set ); }
virtual TU_Ref *newRef() { return remember( new TU_Ref(), JPTI_Ref ); }
virtual TU_GetRef *newGetRef() { return remember( new TU_GetRef(), JPTI_GetRef ); }
virtual TU_SetRef *newSetRef() { return remember( new TU_SetRef(), JPTI_SetRef ); }
virtual TU_Method *newExecution() { return remember (new TU_Method, JPTI_Execution); }
virtual TU_Construction *newConstruction() { return remember (new TU_Construction, JPTI_Construction); }
virtual TU_Destruction *newDestruction() { return remember (new TU_Destruction, JPTI_Destruction); }
virtual TU_Pointcut *newPointcut() { return remember (new TU_Pointcut, JPTI_Pointcut); }
virtual TU_Attribute *newAttribute() { return remember (new TU_Attribute, JPTI_Attribute); }
virtual TU_AdviceCode *newAdviceCode() { return remember (new TU_AdviceCode, JPTI_AdviceCode); }
virtual TU_Introduction *newIntroduction() { return remember (new TU_Introduction, JPTI_Introduction); }
virtual TU_Order *newOrder() { return remember (new TU_Order, JPTI_Order); }
virtual TU_Aspect *newAspect() { return remember (new TU_Aspect, JPTI_Aspect); }
void add_source_loc (ACM_Any *name, clang::SourceLocation location, clang::SourceLocation endlocation, SourceLocKind kind = SLK_NONE);
void add_source_loc (ACM_Any *name, clang::Decl *tree, SourceLocKind kind = SLK_NONE);
void add_source_loc (ACM_Any *name, clang::Stmt *tree, SourceLocKind kind = SLK_NONE);
void add_source_loc (ACM_Any *name, ClangToken token, ClangToken end_token, SourceLocKind kind = SLK_NONE);
// Analyze a declaration and add found attributes to the model element 'name'
void handle_attributes (ACM_Name *name, const clang::AttrVec &attrs, bool is_first_decl = true);
// TODO: temporary solution
// FIXME: needs to be ported to clang
// const list<AccessInfo> &access_infos () const { return _access_infos; }
};
#endif
|