Inferno
0.2
|
00001 #ifndef PARSE_HPP 00002 #define PARSE_HPP 00003 00004 #include "common/common.hpp" 00005 00006 #include "llvm/ADT/APInt.h" 00007 #include "llvm/ADT/APSInt.h" 00008 #include "llvm/ADT/APFloat.h" 00009 #include "llvm/ADT/SmallString.h" 00010 #include "llvm/Support/raw_ostream.h" 00011 00012 #include "clang/Basic/FileManager.h" 00013 #include "clang/Basic/Diagnostic.h" 00014 #include "clang/Basic/LangOptions.h" 00015 #include "clang/Basic/TokenKinds.h" 00016 #include "clang/Basic/TargetInfo.h" 00017 #include "clang/Basic/SourceManager.h" 00018 #include "clang/Lex/HeaderSearch.h" 00019 #include "clang/Lex/Preprocessor.h" 00020 #include "clang/Basic/IdentifierTable.h" 00021 #include "clang/Parse/Action.h" 00022 #include "clang/Parse/Parser.h" 00023 #include "clang/Parse/DeclSpec.h" 00024 #include "clang/Parse/Designator.h" 00025 #include "clang/Parse/Scope.h" 00026 #include "clang/Driver/TextDiagnosticPrinter.h" 00027 #include "clang/Lex/LiteralSupport.h" 00028 00029 #include "tree/cpptree.hpp" 00030 #include "helpers/transformation.hpp" 00031 #include "common/trace.hpp" 00032 #include "tree/type_db.hpp" 00033 #include "tree/misc.hpp" 00034 #include "tree/typeof.hpp" 00035 00036 #include "rc_hold.hpp" 00037 #include "identifier_tracker.hpp" 00038 00039 using namespace CPPTree; // TODO put parse in cpp file so this using does not pollute 00040 00041 #define INFERNO_TRIPLE "arm-linux" 00042 00043 class Parse: public InPlaceTransformation 00044 { 00045 public: 00046 using Transformation::operator(); 00047 Parse(string i) : 00048 infile(i) 00049 { 00050 } 00051 00052 void operator()(TreePtr<Node> context, TreePtr<Node> *proot) 00053 { 00054 // Allow proot to point to a NULL TreePtr; in this case we will create a Program node and parse into it. 00055 // Otherwise *proot must be a Scope, and we will append whatever we parse into that scope. 00056 ASSERT( proot ); 00057 if (!*proot) 00058 { 00059 *proot = TreePtr<Program> (new Program); 00060 } 00061 if (!context) 00062 context = *proot; 00063 TreePtr<Scope> root_scope = dynamic_pointer_cast<Scope> (*proot); 00064 ASSERT(root_scope)("Can only parse into a scope"); 00065 00066 clang::FileManager fm; 00067 llvm::raw_stderr_ostream errstream; // goes to stderr 00068 clang::TextDiagnosticPrinter diag_printer(errstream); 00069 clang::Diagnostic diags(&diag_printer); 00070 clang::LangOptions opts; 00071 opts.CPlusPlus = 1; // Note: always assume input is C++, even if file ends in .c 00072 clang::TargetInfo* ptarget = clang::TargetInfo::CreateTargetInfo( 00073 INFERNO_TRIPLE); 00074 ASSERT(ptarget); 00075 clang::SourceManager sm; 00076 clang::HeaderSearch headers(fm); 00077 00078 std::vector<clang::DirectoryLookup> dirs; 00079 dirs.push_back( clang::DirectoryLookup( fm.getDirectory( string(get_current_dir_name()) + string("/resource/include") ), 00080 clang::SrcMgr::C_System, 00081 true, 00082 false ) ); // TODO would prefer based on location of exe rather than CWD 00083 headers.SetSearchPaths( dirs, 0, false ); // make the directory in dirs be a system directory 00084 00085 clang::Preprocessor pp(diags, opts, *ptarget, sm, headers); 00086 pp.setPredefines("#define __INFERNO__ 1\n"); 00087 00088 const clang::FileEntry *file = fm.getFile(infile); 00089 if (file) 00090 sm.createMainFileID(file, clang::SourceLocation()); 00091 if (sm.getMainFileID() == 0) 00092 { 00093 fprintf(stderr, "Error reading '%s'!\n", infile.c_str()); 00094 exit(1); 00095 } 00096 pp.EnterMainSourceFile(); 00097 00098 clang::IdentifierTable it(opts); 00099 InfernoAction actions(context, root_scope, it, pp, *ptarget); 00100 clang::Parser parser(pp, actions); 00101 TRACE("Start parse\n"); 00102 parser.ParseTranslationUnit(); 00103 ASSERT( !diags.hasErrorOccurred() )("Will not proceed into inferno because clang reported errors\n"); 00104 TRACE("End parse\n"); 00105 } 00106 00107 private: 00108 string infile; 00109 00110 class InfernoAction: public clang::Action 00111 { 00112 public: 00113 InfernoAction(TreePtr<Node> context, TreePtr<Scope> root_scope, 00114 clang::IdentifierTable &IT, clang::Preprocessor &pp, 00115 clang::TargetInfo &T) : 00116 preprocessor(pp), target_info(T), ident_track(context), 00117 global_scope(context), all_decls(new Program) // TODO Scope not Program 00118 { 00119 ASSERT( context ); 00120 ASSERT( root_scope ); 00121 inferno_scope_stack.push(root_scope); // things will be pushed into here 00122 backing_ordering[inferno_scope_stack.top()].clear(); 00123 } 00124 00125 ~InfernoAction() 00126 { 00127 inferno_scope_stack.pop(); 00128 assert( inferno_scope_stack.empty() ); 00129 } 00130 00131 private: 00132 // Parameters are parsed outside function scope, so we defer entering them 00133 // into the ident_track until we're in the function. This stores the clang identifiers. 00134 map<TreePtr<Declaration> , clang::IdentifierInfo *> backing_params; 00135 00136 // The statement after a label is parsed as a sub-construct under the label which 00137 // is not how the inferno tree does it. Remember that relationship here and 00138 // generate the extra nodes when rendering a compound statement. 00139 map<TreePtr<Label> , TreePtr<Statement> > backing_labels; 00140 map<TreePtr<SwitchTarget> , TreePtr<Statement> > backing_targets; 00141 Map<TreePtr<Declaration> , TreePtr<Declaration> > 00142 backing_paired_decl; 00143 00144 // Members of records go in an unordered collection, but when parsing 00145 // we might need the order, eg for C-style initialisers or auto-generated 00146 // constructor calls. 00147 Map<TreePtr<Scope> , Sequence<Declaration> > backing_ordering; 00148 00149 // In ActOnTag, when we see a record decl, we store it here and generate it 00150 // at the next IssueDeclaration, called from ActOnDeclaration. This allows 00151 // a seperate decl for records, since we so not support anon ones, and only 00152 // allow one thing to be decl'd at a time. 00153 TreePtr<Declaration> decl_to_insert; 00154 00155 clang::Preprocessor &preprocessor; 00156 clang::TargetInfo &target_info; 00157 00158 stack<TreePtr<Scope> > inferno_scope_stack; 00159 RCHold<Declaration, DeclTy *> hold_decl; 00160 RCHold<Base, DeclTy *> hold_base; 00161 RCHold<Expression, ExprTy *> hold_expr; 00162 RCHold<Statement, StmtTy *> hold_stmt; 00163 RCHold<Type, TypeTy *> hold_type; 00164 RCHold<LabelIdentifier, void *> hold_label_identifier; 00165 RCHold<Node, CXXScopeTy *> hold_scope; 00166 IdentifierTracker ident_track; 00167 TreePtr<Node> global_scope; 00168 TreePtr<Program> all_decls; // not the actual program, just a flattening of the decls 00169 // we maintain this because decls don't always make it 00170 // into the tree by the time we need them, thanks to the 00171 // way clang works. Decls go in here immediately. 00172 00173 OwningStmtResult ToStmt(TreePtr<Statement> s) 00174 { 00175 return OwningStmtResult(*this, hold_stmt.ToRaw(s)); 00176 } 00177 00178 OwningExprResult ToExpr(TreePtr<Expression> e) 00179 { 00180 return OwningExprResult(*this, hold_expr.ToRaw(e)); 00181 } 00182 00183 TreePtr<Statement> FromClang(const StmtArg &s) 00184 { 00185 return hold_stmt.FromRaw(s.get()); 00186 } 00187 00188 TreePtr<Expression> FromClang(const ExprArg &e) 00189 { 00190 return hold_expr.FromRaw(e.get()); 00191 } 00192 00193 struct DeclarationAsStatement: Statement 00194 { 00195 NODE_FUNCTIONS 00196 TreePtr<Declaration> d; 00197 }; 00198 00199 struct DeclarationChain: Declaration 00200 { 00201 NODE_FUNCTIONS 00202 TreePtr<Declaration> first; 00203 TreePtr<Declaration> second; 00204 }; 00205 00206 // Turn a clang::CXXScopeSpec into a pointer to the corresponding scope node. 00207 // We have to deal with all the ways of it baing invalid, then just use hold_scope. 00208 TreePtr<Node> FromCXXScope(const clang::CXXScopeSpec *SS) 00209 { 00210 if (!SS) 00211 return TreePtr<Node> (); 00212 00213 if (SS->isEmpty()) 00214 return TreePtr<Node> (); 00215 00216 if (!SS->isSet()) 00217 return TreePtr<Node> (); 00218 00219 return hold_scope.FromRaw(SS->getScopeRep()); 00220 } 00221 00222 clang::Action::TypeTy *isTypeName(clang::IdentifierInfo &II, 00223 clang::Scope *S, const clang::CXXScopeSpec *SS) 00224 { 00225 TreePtr<Node> n = ident_track.TryGet(&II, FromCXXScope(SS)); 00226 if (n) 00227 { 00228 TreePtr<UserType> t = dynamic_pointer_cast<UserType> (n); 00229 if (t) 00230 return hold_type.ToRaw(t->identifier); 00231 } 00232 00233 return 0; 00234 } 00235 00236 virtual DeclTy *isTemplateName(clang::IdentifierInfo &II, 00237 clang::Scope *S, const clang::CXXScopeSpec *SS = 0) 00238 { 00239 return 0; // TODO templates 00240 } 00241 00242 virtual bool isCurrentClassName(const clang::IdentifierInfo& II, 00243 clang::Scope *S, const clang::CXXScopeSpec *SS) 00244 { 00245 TRACE(); 00246 ident_track.SeenScope(S); 00247 00248 TreePtr<Node> cur = ident_track.GetCurrent(); 00249 if (!dynamic_pointer_cast<Record> (cur)) 00250 return false; // not even in a record 00251 00252 TreePtr<Node> cxxs = FromCXXScope(SS); 00253 TreePtr<Node> n = ident_track.TryGet(&II, cxxs); 00254 return n == cur; 00255 } 00256 00257 virtual void ActOnPopScope(clang::SourceLocation Loc, clang::Scope *S) 00258 { 00259 TRACE(); 00260 ident_track.PopScope(S); 00261 } 00262 00263 TreePtr<Integral> CreateIntegralType(int bits, bool default_signed, 00264 clang::DeclSpec::TSS type_spec_signed = 00265 clang::DeclSpec::TSS_unspecified) 00266 { 00267 TreePtr<Integral> i; 00268 bool sign; 00269 switch (type_spec_signed) 00270 { 00271 case clang::DeclSpec::TSS_signed: 00272 sign = true; 00273 break; 00274 case clang::DeclSpec::TSS_unsigned: 00275 sign = false; 00276 break; 00277 case clang::DeclSpec::TSS_unspecified: 00278 sign = default_signed; 00279 break; 00280 } 00281 00282 if (sign) 00283 i = TreePtr<Signed> (new Signed); 00284 else 00285 i = TreePtr<Unsigned> (new Unsigned); 00286 00287 i->width = CreateNumericConstant(bits); 00288 return i; 00289 } 00290 00291 TreePtr<Floating> CreateFloatingType(const llvm::fltSemantics *s) 00292 { 00293 ASSERT(s); 00294 TreePtr<SpecificFloatSemantics> sem( 00295 new SpecificFloatSemantics(s)); 00296 TreePtr<Floating> f(new Floating); 00297 f->semantics = sem; 00298 return f; 00299 } 00300 00301 void FillParameters(TreePtr<CallableParams> p, 00302 const clang::DeclaratorChunk::FunctionTypeInfo &fchunk) 00303 { 00304 backing_ordering[p].clear(); // ensure at least an empty sequence is in the map 00305 for (int i = 0; i < fchunk.NumArgs; i++) 00306 { 00307 TreePtr<Declaration> d = hold_decl.FromRaw( 00308 fchunk.ArgInfo[i].Param); 00309 TreePtr<Instance> inst = dynamic_pointer_cast<Instance> (d); 00310 ASSERT( inst ); 00311 backing_ordering[p].push_back(inst); 00312 p->members.insert(inst); 00313 } 00314 } 00315 00316 TreePtr<Type> CreateTypeNode(clang::Declarator &D, int depth = 0) 00317 { 00318 ASSERT( depth>=0 ); 00319 ASSERT( depth<=D.getNumTypeObjects() ); 00320 00321 if (depth == D.getNumTypeObjects()) 00322 { 00323 const clang::DeclSpec &DS = D.getDeclSpec(); 00324 clang::DeclSpec::TST t = DS.getTypeSpecType(); 00325 ASSERT( DS.getTypeSpecComplex() == clang::DeclSpec::TSC_unspecified )( 00326 "complex types not supported"); 00327 switch (t) 00328 { 00329 case clang::DeclSpec::TST_int: 00330 case clang::DeclSpec::TST_unspecified: 00331 TRACE("int based %d %d\n", DS.getTypeSpecWidth(), 00332 DS.getTypeSpecSign()); 00333 return CreateIntegralType( 00334 TypeDb::integral_bits[DS.getTypeSpecWidth()], 00335 TypeDb::int_default_signed, DS.getTypeSpecSign()); 00336 break; 00337 case clang::DeclSpec::TST_char: 00338 TRACE("char based %d %d\n", DS.getTypeSpecWidth(), 00339 DS.getTypeSpecSign()); 00340 return CreateIntegralType(TypeDb::char_bits, 00341 TypeDb::char_default_signed, DS.getTypeSpecSign()); 00342 break; 00343 case clang::DeclSpec::TST_void: 00344 TRACE("void based %d %d\n", DS.getTypeSpecWidth(), 00345 DS.getTypeSpecSign()); 00346 return TreePtr<Type> (new Void()); 00347 break; 00348 case clang::DeclSpec::TST_bool: 00349 TRACE("bool based %d %d\n", DS.getTypeSpecWidth(), 00350 DS.getTypeSpecSign()); 00351 return TreePtr<Type> (new Boolean()); 00352 break; 00353 case clang::DeclSpec::TST_float: 00354 TRACE("float based %d %d\n", DS.getTypeSpecWidth(), 00355 DS.getTypeSpecSign()); 00356 return CreateFloatingType(TypeDb::float_semantics); 00357 break; 00358 case clang::DeclSpec::TST_double: 00359 TRACE("double based %d %d\n", DS.getTypeSpecWidth(), 00360 DS.getTypeSpecSign()); 00361 return CreateFloatingType( 00362 DS.getTypeSpecWidth() == clang::DeclSpec::TSW_long ? TypeDb::long_double_semantics 00363 : TypeDb::double_semantics); 00364 break; 00365 case clang::DeclSpec::TST_typedef: 00366 TRACE("typedef\n"); 00367 return hold_type.FromRaw(DS.getTypeRep()); 00368 break; 00369 case clang::DeclSpec::TST_struct: 00370 case clang::DeclSpec::TST_union: 00371 case clang::DeclSpec::TST_class: 00372 case clang::DeclSpec::TST_enum: 00373 TRACE("struct/union/class/enum\n"); 00374 // Disgustingly, clang casts the DeclTy returned from ActOnTag() to 00375 // a TypeTy. 00376 return dynamic_pointer_cast<Record> (hold_decl.FromRaw( 00377 DS.getTypeRep()))->identifier; 00378 break; 00379 default: 00380 ASSERTFAIL("unsupported type") 00381 ; 00382 break; 00383 } 00384 } 00385 else 00386 { 00387 const clang::DeclaratorChunk &chunk = D.getTypeObject(depth); 00388 switch (chunk.Kind) 00389 { 00390 case clang::DeclaratorChunk::Function: 00391 { 00392 const clang::DeclaratorChunk::FunctionTypeInfo &fchunk = 00393 chunk.Fun; 00394 switch (D.getKind()) 00395 { 00396 case clang::Declarator::DK_Normal: 00397 { 00398 TreePtr<Function> f(new Function); 00399 FillParameters(f, fchunk); 00400 f->return_type = CreateTypeNode(D, depth + 1); 00401 return f; 00402 } 00403 case clang::Declarator::DK_Constructor: 00404 { 00405 TreePtr<Constructor> c(new Constructor); 00406 FillParameters(c, fchunk); 00407 return c; 00408 } 00409 case clang::Declarator::DK_Destructor: 00410 { 00411 TreePtr<Destructor> d(new Destructor); 00412 return d; 00413 } 00414 default: 00415 ASSERT("Unknown function kind\n"); 00416 break; 00417 } 00418 } 00419 00420 case clang::DeclaratorChunk::Pointer: 00421 { 00422 // TODO attributes 00423 TRACE("pointer to...\n"); 00424 const clang::DeclaratorChunk::PointerTypeInfo &pchunk = 00425 chunk.Ptr; 00426 TreePtr<Pointer> p(new Pointer); 00427 p->destination = CreateTypeNode(D, depth + 1); 00428 return p; 00429 } 00430 00431 case clang::DeclaratorChunk::Reference: 00432 { 00433 // TODO attributes 00434 TRACE("reference to...\n"); 00435 const clang::DeclaratorChunk::ReferenceTypeInfo &rchunk = 00436 chunk.Ref; 00437 TreePtr<Reference> r(new Reference); 00438 ASSERT(r); 00439 r->destination = CreateTypeNode(D, depth + 1); 00440 return r; 00441 } 00442 00443 case clang::DeclaratorChunk::Array: 00444 { 00445 // TODO attributes 00446 const clang::DeclaratorChunk::ArrayTypeInfo &achunk = 00447 chunk.Arr; 00448 TRACE("array [%d] of...\n", achunk.NumElts); 00449 TreePtr<Array> a(new Array); 00450 ASSERT(a); 00451 a->element = CreateTypeNode(D, depth + 1); 00452 if (achunk.NumElts) 00453 a->size = hold_expr.FromRaw(achunk.NumElts); // number of elements was specified 00454 else 00455 a->size = MakeTreePtr<Uninitialised> (); // number of elements was not specified eg int a[]; 00456 return a; 00457 } 00458 00459 default: 00460 ASSERTFAIL("Unknown type chunk") 00461 ; 00462 break; 00463 } 00464 } 00465 } 00466 00467 TreePtr<InstanceIdentifier> CreateInstanceIdentifier( 00468 clang::IdentifierInfo *ID = 0) 00469 { 00470 if (ID) 00471 { 00472 TreePtr<SpecificInstanceIdentifier> ii( 00473 new SpecificInstanceIdentifier(ID->getName())); 00474 return ii; 00475 } 00476 else 00477 { 00478 TreePtr<SpecificInstanceIdentifier> ii( 00479 new SpecificInstanceIdentifier); 00480 return ii; 00481 } 00482 } 00483 00484 TreePtr<TypeIdentifier> CreateTypeIdentifier( 00485 clang::IdentifierInfo *ID) 00486 { 00487 ASSERT( ID ); 00488 TreePtr<SpecificTypeIdentifier> ti(new SpecificTypeIdentifier( 00489 ID->getName())); 00490 return ti; 00491 } 00492 00493 TreePtr<TypeIdentifier> CreateTypeIdentifier(string s) 00494 { 00495 TreePtr<SpecificTypeIdentifier> 00496 ti(new SpecificTypeIdentifier(s)); 00497 return ti; 00498 } 00499 00500 TreePtr<LabelIdentifier> CreateLabelIdentifier( 00501 clang::IdentifierInfo *ID) 00502 { 00503 ASSERT( ID ); 00504 TreePtr<SpecificLabelIdentifier> li(new SpecificLabelIdentifier( 00505 ID->getName())); 00506 return li; 00507 } 00508 00509 TreePtr<Instance> CreateInstanceNode(clang::Scope *S, 00510 clang::Declarator &D, TreePtr<AccessSpec> access = 00511 TreePtr<AccessSpec> (), bool automatic = false) 00512 { 00513 TRACE(); 00514 const clang::DeclSpec &DS = D.getDeclSpec(); 00515 if (!access) 00516 access = TreePtr<Private> (new Private); // Most scopes are private unless specified otherwise 00517 00518 TreePtr<Constancy> constancy; 00519 if (DS.getTypeQualifiers() & clang::DeclSpec::TQ_const) 00520 constancy = MakeTreePtr<Const> (); 00521 else 00522 constancy = MakeTreePtr<NonConst> (); 00523 00524 TreePtr<Instance> o; 00525 00526 if (automatic) 00527 { 00528 o = MakeTreePtr<Automatic> (); 00529 } 00530 else 00531 { 00532 clang::DeclSpec::SCS scs = DS.getStorageClassSpec(); 00533 switch (scs) 00534 { 00535 case clang::DeclSpec::SCS_unspecified: 00536 { 00537 TRACE("scope flags 0x%x\n", S->getFlags()); 00538 if (S->getFlags() & clang::Scope::CXXClassScope) // record scope 00539 { 00540 TreePtr<Field> no = MakeTreePtr<Field> (); 00541 o = no; 00542 if (DS.isVirtualSpecified()) 00543 { 00544 no->virt = MakeTreePtr<Virtual> (); 00545 } 00546 else 00547 { 00548 no->virt = MakeTreePtr<NonVirtual> (); 00549 } 00550 no->access = access; 00551 no->constancy = constancy; 00552 } 00553 else if (S->getFnParent()) // in code 00554 { 00555 o = MakeTreePtr<Automatic> (); 00556 } 00557 else // top level 00558 { 00559 TreePtr<Static> no = MakeTreePtr<Static> (); 00560 o = no; 00561 no->constancy = constancy; 00562 } 00563 break; 00564 } 00565 case clang::DeclSpec::SCS_auto: 00566 o = MakeTreePtr<Automatic> (); 00567 break; 00568 case clang::DeclSpec::SCS_extern:// linking will be done "automatically" so no need to remember "extern" in the tree 00569 { 00570 TreePtr<Static> no = MakeTreePtr<Static> (); 00571 o = no; 00572 no->constancy = constancy; 00573 } 00574 break; 00575 case clang::DeclSpec::SCS_static: 00576 { 00577 TreePtr<Static> no = MakeTreePtr<Static> (); 00578 o = no; 00579 no->constancy = constancy; 00580 } 00581 break; 00582 default: 00583 ASSERTFAIL("Unsupported storage class") 00584 ; 00585 break; 00586 } 00587 } 00588 00589 all_decls->members.insert(o); 00590 00591 clang::IdentifierInfo *ID = D.getIdentifier(); 00592 if (ID) 00593 { 00594 o->identifier = CreateInstanceIdentifier(ID); 00595 ident_track.Add(ID, o, S); 00596 } 00597 else 00598 { 00599 o->identifier = CreateInstanceIdentifier(); 00600 } 00601 o->type = CreateTypeNode(D); 00602 o->initialiser = MakeTreePtr<Uninitialised> (); 00603 00604 return o; 00605 } 00606 00607 TreePtr<Typedef> CreateTypedefNode(clang::Scope *S, 00608 clang::Declarator &D) 00609 { 00610 TreePtr<Typedef> t(new Typedef); 00611 all_decls->members.insert(t); 00612 clang::IdentifierInfo *ID = D.getIdentifier(); 00613 if (ID) 00614 { 00615 t->identifier = CreateTypeIdentifier(ID); 00616 ident_track.Add(ID, t, S); 00617 } 00618 t->type = CreateTypeNode(D); 00619 00620 TRACE("%s %p %p\n", ID->getName(), t.get(), ID); 00621 return t; 00622 } 00623 /* 00624 TreePtr<Label> CreateLabelNode( clang::IdentifierInfo *ID ) 00625 { 00626 TreePtr<Label> l(new Label); 00627 all_decls->members.insert(l); 00628 l->access = MakeTreePtr<Public>(); 00629 l->identifier = CreateLabelIdentifier(ID); 00630 TRACE("%s %p %p\n", ID->getName(), l.get(), ID ); 00631 return l; 00632 } 00633 */ 00634 TreePtr<Declaration> FindExistingDeclaration( 00635 const clang::CXXScopeSpec &SS, clang::IdentifierInfo *ID, 00636 bool recurse) 00637 { 00638 if (!ID) 00639 return TreePtr<Declaration> (); // No name specified => doesn't match anything 00640 00641 // See if we already have this record in the current scope, or specified scope 00642 // if Declarator has one 00643 TreePtr<Node> cxxs = FromCXXScope(&SS); 00644 00645 // Use C++ scope if non-NULL; do not recurse (=precise match only) 00646 TreePtr<Node> found_n = ident_track.TryGet(ID, cxxs, recurse); 00647 TRACE("Looked for %s, result %p (%p)\n", ID->getName(), 00648 found_n.get(), cxxs.get()); 00649 if (!found_n) 00650 { 00651 // Nothing was found with the supplied name 00652 ASSERT( !cxxs ); // If C++ scope was given explicitly, require successful find 00653 return TreePtr<Declaration> (); 00654 } 00655 00656 TreePtr<Declaration> found_d = 00657 dynamic_pointer_cast<Declaration> (found_n); 00658 // If the found match is not a declaration, cast will fail and we'll return NULL for "not found" 00659 return found_d; 00660 } 00661 00662 // Alternative parameters 00663 TreePtr<Declaration> FindExistingDeclaration(clang::Declarator &D, 00664 bool recurse) 00665 { 00666 return FindExistingDeclaration(D.getCXXScopeSpec(), 00667 D.getIdentifier(), recurse); 00668 } 00669 00670 TreePtr<Declaration> CreateDelcaration(clang::Scope *S, 00671 clang::Declarator &D, TreePtr<AccessSpec> a = TreePtr< 00672 AccessSpec> ()) 00673 { 00674 const clang::DeclSpec &DS = D.getDeclSpec(); 00675 TreePtr<Declaration> d; 00676 if (DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef) 00677 { 00678 TreePtr<Typedef> t = CreateTypedefNode(S, D); 00679 TRACE(); 00680 d = t; 00681 } 00682 else 00683 { 00684 TreePtr<Instance> o = CreateInstanceNode(S, D, a); 00685 d = o; 00686 } 00687 00688 return d; 00689 } 00690 00691 // Does 1 thing: 00692 // 1. Inserts a stored decl if there is one in decl_to_insert 00693 void IssueDeclaration(clang::Scope *S, TreePtr<Declaration> d) 00694 { 00695 int os = inferno_scope_stack.top()->members.size(); 00696 // Did we leave a record decl lying around to insert later? If so, pack it together with 00697 // the current instance decl, for insertion into the code sequence. 00698 TRACE("Issuing instance decl ")(*d)(" scope flags %x ", S->getFlags()); 00699 if (decl_to_insert) 00700 { 00701 inferno_scope_stack.top()->members.insert(decl_to_insert); 00702 backing_ordering[inferno_scope_stack.top()].push_back( 00703 decl_to_insert); 00704 backing_paired_decl[d] = decl_to_insert; 00705 decl_to_insert = TreePtr<Declaration> (); // don't need to generate it again 00706 TRACE("inserted record decl\n"); 00707 } 00708 00709 TRACE("no insert record decl\n"); 00710 inferno_scope_stack.top()->members.insert(d); 00711 backing_ordering[inferno_scope_stack.top()].push_back(d); 00712 TRACE("From %d to %d decls\n", os, inferno_scope_stack.top()->members.size() ); 00713 } 00714 00715 virtual DeclTy *ActOnDeclarator(clang::Scope *S, clang::Declarator &D, 00716 DeclTy *LastInGroup) 00717 { 00718 TRACE("Scope S%p\n", S); 00719 ident_track.SeenScope(S); 00720 // TODO the spurious char __builtin_va_list; line comes from the target info. 00721 // Create an inferno target info customised for Inferno that doesn't do this. 00722 if (strcmp(D.getIdentifier()->getName(), "__builtin_va_list") == 0) 00723 { 00724 return 0; 00725 } 00726 00727 TreePtr<Declaration> d = FindExistingDeclaration(D, false); // decl exists already? 00728 if (!d) 00729 { 00730 d = CreateDelcaration(S, D); // make a new one 00731 IssueDeclaration(S, d); 00732 } 00733 00734 // Clang refuses to store all the DeclTys we return in cases like int a, b, c; 00735 // instead it provides us with the last one we parsed (LastInGroup) and we are 00736 // expected to chain them. Use a local node for this and untangle in AddStatementToCompound. 00737 TRACE("LIG=%x\n", LastInGroup); 00738 if( LastInGroup ) 00739 { 00740 TRACE("Chaining declarations\n"); 00741 MakeTreePtr<DeclarationChain> dc; 00742 dc->first = hold_decl.FromRaw(LastInGroup); 00743 dc->second = d; 00744 d = dc; 00745 } 00746 00747 return hold_decl.ToRaw( d ); 00748 } 00749 00750 /// ActOnParamDeclarator - This callback is invoked when a parameter 00751 /// declarator is parsed. This callback only occurs for functions 00752 /// with prototypes. S is the function prototype scope for the 00753 /// parameters (C++ [basic.scope.proto]). 00754 virtual DeclTy *ActOnParamDeclarator(clang::Scope *S, 00755 clang::Declarator &D) 00756 { 00757 00758 TreePtr<Instance> p = CreateInstanceNode(S, D, 00759 MakeTreePtr<Public> (), true); 00760 backing_params[p] = D.getIdentifier(); // allow us to register the object with ident_track once we're in the function body scope 00761 return hold_decl.ToRaw(p); 00762 } 00763 00764 virtual void AddInitializerToDecl(DeclTy *Dcl, ExprArg Init) 00765 { 00766 TRACE(); 00767 TreePtr<Declaration> d = hold_decl.FromRaw(Dcl); 00768 00769 TreePtr<Instance> o = dynamic_pointer_cast<Instance> (d); 00770 ASSERT( o ); // Only objects can be initialised 00771 00772 o->initialiser = FromClang(Init); 00773 00774 // At this point, when we have the instance (and hence the type) and the initialiser 00775 // we can detect when an array initialiser has been inserted for a record instance and 00776 // change it. 00777 if ( TreePtr<MakeArray> ai = dynamic_pointer_cast<MakeArray>(o->initialiser) ) 00778 if ( TreePtr<TypeIdentifier> ti = dynamic_pointer_cast<TypeIdentifier>(o->type) ) 00779 if ( TreePtr<Record> r = GetRecordDeclaration(all_decls, ti) ) 00780 o->initialiser = CreateRecordLiteralFromArrayLiteral( 00781 ai, r); 00782 } 00783 00784 /// AddCXXDirectInitializerToDecl - This action is called immediately after 00785 /// ActOnDeclarator, when a C++ direct initializer is present. 00786 /// e.g: "int x(1);" 00787 virtual void AddCXXDirectInitializerToDecl(DeclTy *Dcl, 00788 clang::SourceLocation LParenLoc, 00789 ExprTy **Exprs, unsigned NumExprs, 00790 clang::SourceLocation *CommaLocs, 00791 clang::SourceLocation RParenLoc) 00792 { 00793 TRACE(); 00794 TreePtr<Declaration> d = hold_decl.FromRaw(Dcl); 00795 TreePtr<Instance> o = dynamic_pointer_cast<Instance> (d); 00796 TRACE("Ignoring C++ direct initialiser for SC Modules, not supported in general\n"); // TODO try the code below... 00797 // TreePtr<Instance> cm = GetConstructor( d->type ); 00798 // ASSERT( cm ); 00799 // ASSERT( cm->identifier ); 00800 // Sequence<Expression> args; 00801 // CollectArgs( &args, Exprs, NumExprs ); 00802 // TreePtr<Call> c = CreateCall( args, cm->identifier ); 00803 } 00804 00805 // Clang tends to parse parameters and function bodies in seperate 00806 // scopes so when we see them being used we don't recognise them 00807 // and cannot link back to the correct Instance node. This function 00808 // puts all the params back in the current scope assuming: 00809 // 1. They have been added to the Function node correctly and 00810 // 2. They feature in the backing list for params 00811 void AddParamsToScope( TreePtr<CallableParams> pp, 00812 clang::Scope *FnBodyScope) 00813 { 00814 ASSERT(pp); 00815 00816 FOREACH(TreePtr<Declaration> param, pp->members ) 00817 { TRACE(); 00818 clang::IdentifierInfo *paramII = backing_params[param]; 00819 backing_params.erase( param ); 00820 TRACE("%p %p %s S%p\n", param.get(), paramII, paramII->getName(), FnBodyScope); 00821 if( paramII ) 00822 ident_track.Add( paramII, param, FnBodyScope ); 00823 } 00824 } 00825 00826 // JSG this is like the default in Actions, except it passes the parent of the function 00827 // body to ActOnDeclarator, since the function decl itself is not inside its own body. 00828 virtual DeclTy *ActOnStartOfFunctionDef(clang::Scope *FnBodyScope, clang::Declarator &D) 00829 { 00830 TRACE(); 00831 // Declarator is outside function sope, otherwise it would be in its own scope and unfindable 00832 DeclTy *DT = ActOnDeclarator(FnBodyScope->getParent(), D, 0); 00833 // Now enter function's scope. Use node from existing declaration so we get any enclosing classes 00834 TreePtr<Node> n = FindExistingDeclaration(D, false); 00835 ident_track.PushScope( FnBodyScope->getParent(), n ); 00836 // Default to ActOnDeclarator. 00837 return ActOnStartOfFunctionDef(FnBodyScope, DT); 00838 } 00839 00840 virtual DeclTy *ActOnStartOfFunctionDef(clang::Scope *FnBodyScope, DeclTy *D) 00841 { 00842 TRACE("FnBodyScope S%p\n", FnBodyScope); 00843 TreePtr<Instance> o = dynamic_pointer_cast<Instance>(hold_decl.FromRaw(D)); 00844 ASSERT(o); 00845 00846 // Note: this line was commented out as of mid August, but I'm sure I put it 00847 // in recently, to fix a bug. Can't remember why it was commented out. Uncommented 00848 // to fix scopes being popped without being pushed. 00849 ident_track.SeenScope( FnBodyScope ); 00850 00851 if( TreePtr<CallableParams> pp = dynamic_pointer_cast<CallableParams>( o->type ) ) 00852 AddParamsToScope( pp, FnBodyScope ); 00853 00854 // This is just a junk scope because we will not use scopes collected 00855 // via the inferno_scope_stack mechanism within functions; instead, they 00856 // will appear among the Statements managed by clang and passed into 00857 // ActOnFinishFunctionBody() as a hierarchy of Compounds. 00858 // If we tried to do this ourselves we'd lose the nested compound 00859 // statement hierarchy. 00860 inferno_scope_stack.push( TreePtr<Scope>(new Scope) ); 00861 00862 return hold_decl.ToRaw( o ); 00863 } 00864 00865 virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body) 00866 { 00867 TRACE(); 00868 TreePtr<Instance> o( dynamic_pointer_cast<Instance>( hold_decl.FromRaw(Decl) ) ); 00869 ASSERT(o); 00870 TreePtr<Compound> cb( dynamic_pointer_cast<Compound>( FromClang( Body ) ) ); 00871 ASSERT(cb); // function body must be a scope or 0 00872 00873 if( dynamic_pointer_cast<Uninitialised>( o->initialiser ) ) 00874 o->initialiser = cb; 00875 else if( TreePtr<Compound> c = dynamic_pointer_cast<Compound>( o->initialiser ) ) 00876 c->statements = c->statements + cb->statements; 00877 else 00878 ASSERTFAIL("wrong thing in function instance"); 00879 00880 TRACE("finish fn %d statements %d total\n", cb->statements.size(), (dynamic_pointer_cast<Compound>(o->initialiser))->statements.size() ); 00881 00882 inferno_scope_stack.pop(); // we dont use these - we use the clang-managed compound statement instead (passed in via Body) 00883 ident_track.PopScope(NULL); 00884 return Decl; 00885 } 00886 00887 virtual OwningStmtResult ActOnExprStmt(ExprArg Expr) 00888 { 00889 // TODO most of this is now unnecessary 00890 if( TreePtr<Expression> e = dynamic_pointer_cast<Expression>( FromClang(Expr) ) ) 00891 { 00892 return ToStmt( e ); 00893 } 00894 else 00895 { 00896 // Operands that are not Expressions have no side effects and so 00897 // they do nothing as Statements 00898 TreePtr<Nop> n(new Nop); 00899 return ToStmt( n ); 00900 } 00901 } 00902 00903 virtual StmtResult ActOnReturnStmt( clang::SourceLocation ReturnLoc, 00904 ExprTy *RetValExp ) 00905 { 00906 TreePtr<Return> r(new Return); 00907 if( RetValExp ) 00908 r->return_value = hold_expr.FromRaw(RetValExp); 00909 else 00910 r->return_value = MakeTreePtr<Uninitialised>(); 00911 TRACE("aors %p\n", r.get() ); 00912 return hold_stmt.ToRaw( r ); 00913 } 00914 00915 virtual ExprResult ActOnIdentifierExpr( clang::Scope *S, 00916 clang::SourceLocation Loc, 00917 clang::IdentifierInfo &II, 00918 bool HasTrailingLParen, 00919 const clang::CXXScopeSpec *SS = 0 ) 00920 { 00921 TRACE("S%p\n", S); 00922 TreePtr<Node> n = ident_track.Get( &II, FromCXXScope( SS ) ); 00923 TRACE("aoie %s %s\n", II.getName(), typeid(*n).name() ); 00924 TreePtr<Instance> o = dynamic_pointer_cast<Instance>( n ); 00925 ASSERT( o ); 00926 return hold_expr.ToRaw( o->identifier ); 00927 } 00928 00929 TreePtr<Integer> CreateNumericConstant( int value ) 00930 { 00931 TreePtr<SpecificInteger> nc( new SpecificInteger(value) ); 00932 return nc; 00933 } 00934 00935 TreePtr<Literal> CreateLiteral( int value ) 00936 { 00937 return CreateNumericConstant( value ); 00938 } 00939 00940 TreePtr<Number> CreateNumericConstant(const clang::Token &tok) 00941 { 00942 llvm::SmallString<512> int_buffer; 00943 int_buffer.resize(tok.getLength()); 00944 const char *this_tok_begin = &int_buffer[0]; 00945 00946 // Get the spelling of the token, which eliminates trigraphs, etc. 00947 unsigned actual_length = preprocessor.getSpelling(tok, this_tok_begin); 00948 clang::NumericLiteralParser literal(this_tok_begin, this_tok_begin+actual_length, 00949 tok.getLocation(), preprocessor); 00950 ASSERT(!literal.hadError); 00951 00952 if (literal.isIntegerLiteral()) 00953 { 00954 int bits; 00955 if( literal.isLong ) 00956 bits = TypeDb::integral_bits[clang::DeclSpec::TSW_long]; 00957 else if( literal.isLongLong ) 00958 bits = TypeDb::integral_bits[clang::DeclSpec::TSW_longlong]; 00959 else 00960 bits = TypeDb::integral_bits[clang::DeclSpec::TSW_unspecified]; 00961 00962 llvm::APSInt rv(bits, literal.isUnsigned); 00963 bool err = literal.GetIntegerValue(rv); 00964 00965 ASSERT( !err )( "numeric literal too big for its own type" ); 00966 TreePtr<SpecificInteger> nc( new SpecificInteger(rv) ); 00967 return nc; 00968 } 00969 else if( literal.isFloatingLiteral() ) 00970 { 00971 const llvm::fltSemantics *semantics; 00972 if( literal.isLong ) 00973 semantics = TypeDb::long_double_semantics; 00974 else if( literal.isFloat ) 00975 semantics = TypeDb::float_semantics; 00976 else 00977 semantics = TypeDb::double_semantics; 00978 llvm::APFloat rv( literal.GetFloatValue( *semantics ) ); 00979 00980 TreePtr<SpecificFloat> fc( new SpecificFloat( rv ) ); 00981 return fc; 00982 } 00983 ASSERTFAIL("this sort of literal is not supported"); 00984 } 00985 00986 virtual ExprResult ActOnNumericConstant(const clang::Token &tok) 00987 { 00988 return hold_expr.ToRaw( CreateNumericConstant( tok ) ); 00989 } 00990 00991 virtual ExprResult ActOnBinOp(clang::Scope *S, 00992 clang::SourceLocation TokLoc, clang::tok::TokenKind Kind, 00993 ExprTy *LHS, ExprTy *RHS) 00994 { 00995 TRACE(); 00996 TreePtr<Operator> o = TreePtr<Operator>(); 00997 switch( Kind ) 00998 { 00999 #define INFIX(TOK, TEXT, NODE, BASE, CAT) \ 01000 case clang::tok::TOK: \ 01001 o=TreePtr<NODE>(new NODE);\ 01002 break; 01003 #include "tree/operator_db.inc" 01004 } 01005 ASSERT( o ); 01006 if( TreePtr<NonCommutativeOperator> nco = dynamic_pointer_cast< NonCommutativeOperator >(o) ) 01007 { 01008 nco->operands.push_back( hold_expr.FromRaw(LHS) ); 01009 nco->operands.push_back( hold_expr.FromRaw(RHS) ); 01010 } 01011 else if( TreePtr<CommutativeOperator> co = dynamic_pointer_cast< CommutativeOperator >(o) ) 01012 { 01013 co->operands.insert( hold_expr.FromRaw(LHS) ); 01014 co->operands.insert( hold_expr.FromRaw(RHS) ); 01015 } 01016 else 01017 ASSERTFAIL("Binop was apparently neither Commutative nor NonCommutative"); 01018 01019 return hold_expr.ToRaw( o ); 01020 } 01021 01022 virtual ExprResult ActOnPostfixUnaryOp(clang::Scope *S, clang::SourceLocation OpLoc, 01023 clang::tok::TokenKind Kind, ExprTy *Input) 01024 { 01025 TreePtr<NonCommutativeOperator> o = TreePtr<NonCommutativeOperator>(); 01026 01027 switch( Kind ) 01028 { 01029 #define POSTFIX(TOK, TEXT, NODE, BASE, CAT) \ 01030 case clang::tok::TOK: \ 01031 o=TreePtr<NODE>(new NODE); \ 01032 break; 01033 #include "tree/operator_db.inc" 01034 } 01035 ASSERT( o ); 01036 o->operands.push_back( hold_expr.FromRaw(Input) ); 01037 return hold_expr.ToRaw( o ); 01038 } 01039 01040 virtual ExprResult ActOnUnaryOp( clang::Scope *S, clang::SourceLocation OpLoc, 01041 clang::tok::TokenKind Kind, ExprTy *Input) 01042 { 01043 TreePtr<NonCommutativeOperator> o = TreePtr<NonCommutativeOperator>(); 01044 01045 switch( Kind ) 01046 { 01047 #define PREFIX(TOK, TEXT, NODE, BASE, CAT) \ 01048 case clang::tok::TOK:\ 01049 o=TreePtr<NODE>(new NODE); \ 01050 break; 01051 #include "tree/operator_db.inc" 01052 } 01053 ASSERT( o ); 01054 o->operands.push_back( hold_expr.FromRaw(Input) ); 01055 return hold_expr.ToRaw( o ); 01056 } 01057 01058 virtual ExprResult ActOnConditionalOp(clang::SourceLocation QuestionLoc, 01059 clang::SourceLocation ColonLoc, 01060 ExprTy *Cond, ExprTy *LHS, ExprTy *RHS) 01061 { 01062 TreePtr<Multiplexor> co(new Multiplexor); 01063 co->operands.push_back( hold_expr.FromRaw(Cond) ); 01064 ASSERT(LHS )( "gnu extension not supported"); 01065 co->operands.push_back( hold_expr.FromRaw(LHS) ); 01066 co->operands.push_back( hold_expr.FromRaw(RHS) ); 01067 return hold_expr.ToRaw( co ); 01068 } 01069 01070 TreePtr<Call> CreateCall( Sequence<Expression> &args, TreePtr<Expression> callee ) 01071 { 01072 // Make the Call node and fill in the called function 01073 TreePtr<Call> c(new Call); 01074 c->callee = callee; 01075 01076 // If CallableParams, fill in the args map based on the supplied args and original function type 01077 TreePtr<Node> t = TypeOf::instance(all_decls, callee); 01078 if( TreePtr<CallableParams> p = dynamic_pointer_cast<CallableParams>(t) ) 01079 PopulateMapOperator( c, args, p ); 01080 01081 return c; 01082 } 01083 01084 virtual ExprResult ActOnCallExpr(clang::Scope *S, ExprTy *Fn, clang::SourceLocation LParenLoc, 01085 ExprTy **Args, unsigned NumArgs, 01086 clang::SourceLocation *CommaLocs, 01087 clang::SourceLocation RParenLoc) 01088 { 01089 // Get the args in a Sequence 01090 Sequence<Expression> args; 01091 CollectArgs( &args, Args, NumArgs ); 01092 TreePtr<Call> c = CreateCall( args, hold_expr.FromRaw(Fn) ); 01093 return hold_expr.ToRaw( c ); 01094 } 01095 01096 // Not sure if this one has been tested!! 01097 virtual TypeResult ActOnTypeName(clang::Scope *S, clang::Declarator &D) 01098 { 01099 TreePtr<Type> t = CreateTypeNode( D ); 01100 return hold_type.ToRaw( t ); 01101 } 01102 01103 void AddDeclarationToCompound( TreePtr<Compound> s, TreePtr<Declaration> d ) 01104 { 01105 if( TreePtr<DeclarationChain> dc = dynamic_pointer_cast<DeclarationChain>( d ) ) 01106 { 01107 TRACE("Walking declaration chain\n"); 01108 AddDeclarationToCompound( s, dc->first ); 01109 AddDeclarationToCompound( s, dc->second ); 01110 return; 01111 } 01112 01113 if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>(d) ) 01114 AddStatementToCompound( s, i ); // Instances can have inits that require being in order, so append as a statement 01115 else 01116 s->members.insert( d ); 01117 } 01118 01119 void AddStatementToCompound( TreePtr<Compound> s, TreePtr<Statement> st ) 01120 { 01121 /* if( TreePtr<ParseTwin> pt = dynamic_pointer_cast<ParseTwin>( st ) ) 01122 { 01123 AddStatementToCompound( s, pt->d1 ); 01124 AddStatementToCompound( s, pt->d2 ); 01125 return; 01126 } 01127 */ 01128 if( TreePtr<Declaration> d = dynamic_pointer_cast<Declaration>( st ) ) 01129 { 01130 if( backing_paired_decl.IsExist(d) ) 01131 { 01132 TreePtr<Declaration> bd = backing_paired_decl[d]; 01133 ASSERT( bd ); 01134 AddDeclarationToCompound( s, bd ); 01135 backing_paired_decl.erase(d); 01136 } 01137 } 01138 01139 if( TreePtr<DeclarationAsStatement> das = dynamic_pointer_cast<DeclarationAsStatement>(st) ) 01140 AddDeclarationToCompound( s, das->d ); 01141 else 01142 s->statements.push_back( st ); 01143 01144 // FlattenNode the "sub" statements of labels etc 01145 if( TreePtr<Label> l = dynamic_pointer_cast<Label>( st ) ) 01146 { 01147 ASSERT( backing_labels[l] ); 01148 AddStatementToCompound( s, backing_labels[l] ); 01149 backing_labels.erase(l); 01150 } 01151 else if( TreePtr<SwitchTarget> t = dynamic_pointer_cast<SwitchTarget>( st ) ) 01152 { 01153 ASSERT( backing_targets[t] ); 01154 AddStatementToCompound( s, backing_targets[t] ); 01155 backing_targets.erase(t); 01156 } 01157 } 01158 01159 virtual OwningStmtResult ActOnCompoundStmt(clang::SourceLocation L, clang::SourceLocation R, 01160 MultiStmtArg Elts, 01161 bool isStmtExpr) 01162 { 01163 // TODO helper fn for MultiStmtArg, like FromClang. Maybe. 01164 TreePtr<Compound> s(new Compound); 01165 01166 for( int i=0; i<Elts.size(); i++ ) 01167 AddStatementToCompound( s, hold_stmt.FromRaw( Elts.get()[i] ) ); 01168 01169 return ToStmt( s ); 01170 } 01171 01172 virtual OwningStmtResult ActOnDeclStmt(DeclTy *Decl, clang::SourceLocation StartLoc, 01173 clang::SourceLocation EndLoc) 01174 { 01175 TreePtr<Declaration> d( hold_decl.FromRaw(Decl) ); 01176 // Basically we are being asked to turn a Declaration, which has already been parsed, 01177 // into a Statement. Instances are already both Declarations and Statements, so that's 01178 // OK. In other cases, we have to package up the Declaration in a special kind of 01179 // Statement node and pass it through that way. We will unpack later. 01180 if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>(d) ) 01181 { 01182 return ToStmt( i ); 01183 } 01184 else 01185 { 01186 TreePtr<DeclarationAsStatement> das( new DeclarationAsStatement ); 01187 das->d = d; 01188 return ToStmt( das ); 01189 } 01190 } 01191 01192 // Create a label identifier if there isn't already one with the same name (TODO scopes?) 01193 TreePtr<LabelIdentifier> MaybeCreateLabelIdentifier( clang::IdentifierInfo *II ) 01194 { 01195 if( !(II->getFETokenInfo<void *>()) ) 01196 II->setFETokenInfo( hold_label_identifier.ToRaw( CreateLabelIdentifier( II ) ) ); 01197 01198 return hold_label_identifier.FromRaw( II->getFETokenInfo<void *>() ); 01199 } 01200 01201 virtual StmtResult ActOnLabelStmt(clang::SourceLocation IdentLoc, clang::IdentifierInfo *II, 01202 clang::SourceLocation ColonLoc, StmtTy *SubStmt) 01203 { 01204 TreePtr<Label> l( new Label ); 01205 l->identifier = MaybeCreateLabelIdentifier(II); 01206 backing_labels[l] = hold_stmt.FromRaw( SubStmt ); 01207 return hold_stmt.ToRaw( l ); 01208 } 01209 01210 virtual StmtResult ActOnGotoStmt(clang::SourceLocation GotoLoc, 01211 clang::SourceLocation LabelLoc, 01212 clang::IdentifierInfo *LabelII) 01213 { 01214 TreePtr<Goto> g( new Goto ); 01215 g->destination = MaybeCreateLabelIdentifier(LabelII); 01216 return hold_stmt.ToRaw( g ); 01217 } 01218 01219 virtual StmtResult ActOnIndirectGotoStmt(clang::SourceLocation GotoLoc, 01220 clang::SourceLocation StarLoc, 01221 ExprTy *DestExp) 01222 { 01223 TreePtr<Goto> g( new Goto ); 01224 g->destination = hold_expr.FromRaw( DestExp ); 01225 return hold_stmt.ToRaw( g ); 01226 } 01227 01228 virtual ExprResult ActOnAddrLabel(clang::SourceLocation OpLoc, clang::SourceLocation LabLoc, 01229 clang::IdentifierInfo *LabelII) // "&&foo" 01230 01231 { 01232 // TODO doesn't && meaning label-as-variable conflict with C++0x right-reference thingy? 01233 return hold_expr.ToRaw( MaybeCreateLabelIdentifier(LabelII) ); 01234 } 01235 01236 virtual StmtResult ActOnIfStmt(clang::SourceLocation IfLoc, ExprTy *CondVal, 01237 StmtTy *ThenVal, clang::SourceLocation ElseLoc, 01238 StmtTy *ElseVal) 01239 { 01240 TreePtr<If> i( new If ); 01241 i->condition = hold_expr.FromRaw( CondVal ); 01242 i->body = hold_stmt.FromRaw( ThenVal ); 01243 if( ElseVal ) 01244 i->else_body = hold_stmt.FromRaw( ElseVal ); 01245 else 01246 i->else_body = MakeTreePtr<Nop>(); // empty else clause 01247 return hold_stmt.ToRaw( i ); 01248 } 01249 01250 virtual StmtResult ActOnWhileStmt(clang::SourceLocation WhileLoc, ExprTy *Cond, 01251 StmtTy *Body) 01252 { 01253 TreePtr<While> w( new While ); 01254 w->condition = hold_expr.FromRaw( Cond ); 01255 w->body = hold_stmt.FromRaw( Body ); 01256 return hold_stmt.ToRaw( w ); 01257 } 01258 01259 virtual StmtResult ActOnDoStmt(clang::SourceLocation DoLoc, StmtTy *Body, 01260 clang::SourceLocation WhileLoc, ExprTy *Cond) 01261 { 01262 TreePtr<Do> d( new Do ); 01263 d->body = hold_stmt.FromRaw( Body ); 01264 d->condition = hold_expr.FromRaw( Cond ); 01265 return hold_stmt.ToRaw( d ); 01266 } 01267 01268 virtual StmtResult ActOnForStmt(clang::SourceLocation ForLoc, 01269 clang::SourceLocation LParenLoc, 01270 StmtTy *First, ExprTy *Second, ExprTy *Third, 01271 clang::SourceLocation RParenLoc, StmtTy *Body) 01272 { 01273 TreePtr<For> f( new For ); 01274 if( First ) 01275 f->initialisation = hold_stmt.FromRaw( First ); 01276 else 01277 f->initialisation = MakeTreePtr<Nop>(); 01278 01279 if( Second ) 01280 f->condition = hold_expr.FromRaw( Second ); 01281 else 01282 f->condition = MakeTreePtr<True>(); 01283 01284 StmtTy *third = (StmtTy *)Third; // Third is really a statement, the Actions API is wrong 01285 if( third ) 01286 f->increment = hold_stmt.FromRaw( third ); 01287 else 01288 f->increment = MakeTreePtr<Nop>(); 01289 01290 f->body = hold_stmt.FromRaw( Body ); 01291 return hold_stmt.ToRaw( f ); 01292 } 01293 01294 virtual StmtResult ActOnStartOfSwitchStmt(ExprTy *Cond) 01295 { 01296 TreePtr<Switch> s( new Switch ); 01297 s->condition = hold_expr.FromRaw( Cond ); 01298 return hold_stmt.ToRaw( s ); 01299 } 01300 01301 virtual StmtResult ActOnFinishSwitchStmt(clang::SourceLocation SwitchLoc, 01302 StmtTy *rsw, ExprTy *Body) 01303 { 01304 TreePtr<Statement> s( hold_stmt.FromRaw( rsw ) ); 01305 TreePtr<Switch> sw( dynamic_pointer_cast<Switch>(s) ); 01306 ASSERT(sw)("expecting a switch statement"); 01307 01308 StmtTy *body = (StmtTy *)Body; // Third is really a statement, the Actions API is wrong 01309 sw->body = hold_stmt.FromRaw( body ); 01310 return hold_stmt.ToRaw( s ); 01311 } 01312 01313 /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, 01314 /// which can specify an RHS value. 01315 virtual OwningStmtResult ActOnCaseStmt(clang::SourceLocation CaseLoc, ExprArg LHSVal, 01316 clang::SourceLocation DotDotDotLoc, ExprArg RHSVal, 01317 clang::SourceLocation ColonLoc, StmtArg SubStmt) 01318 { 01319 TRACE(); 01320 01321 if( RHSVal.get() ) 01322 { 01323 TreePtr<RangeCase> rc( new RangeCase ); 01324 rc->value_lo = FromClang( LHSVal ); 01325 rc->value_hi = FromClang( RHSVal ); 01326 backing_targets[rc] = FromClang( SubStmt ); 01327 return ToStmt( rc ); 01328 } 01329 else 01330 { 01331 TreePtr<Case> c( new Case ); 01332 c->value = FromClang( LHSVal ); 01333 backing_targets[c] = FromClang( SubStmt ); 01334 return ToStmt( c ); 01335 } 01336 } 01337 01338 virtual OwningStmtResult ActOnDefaultStmt(clang::SourceLocation DefaultLoc, 01339 clang::SourceLocation ColonLoc, StmtArg SubStmt, 01340 clang::Scope *CurScope) 01341 { 01342 TRACE(); 01343 TreePtr<Default> d( new Default ); 01344 backing_targets[d] = FromClang( SubStmt ); 01345 return ToStmt( d ); 01346 } 01347 01348 virtual StmtResult ActOnContinueStmt(clang::SourceLocation ContinueLoc, 01349 clang::Scope *CurScope) 01350 { 01351 return hold_stmt.ToRaw( TreePtr<Continue>( new Continue ) ); 01352 } 01353 01354 virtual StmtResult ActOnBreakStmt(clang::SourceLocation GotoLoc, clang::Scope *CurScope) 01355 { 01356 return hold_stmt.ToRaw( TreePtr<Break>( new Break ) ); 01357 } 01358 01359 TreePtr<AccessSpec> ConvertAccess( clang::AccessSpecifier AS, TreePtr<Record> rec = TreePtr<Record>() ) 01360 { 01361 switch( AS ) 01362 { 01363 case clang::AS_public: 01364 return TreePtr<Public>(new Public); 01365 break; 01366 case clang::AS_protected: 01367 return TreePtr<Protected>(new Protected); 01368 break; 01369 case clang::AS_private: 01370 return TreePtr<Private>(new Private); 01371 break; 01372 case clang::AS_none: 01373 ASSERT( rec )( "no access specifier and record not supplied so cannot deduce"); 01374 // members are never AS_none because clang deals. Bases can be AS_none, so we supply the enclosing record type 01375 if( dynamic_pointer_cast<Class>(rec) ) 01376 return TreePtr<Private>(new Private); 01377 else 01378 return TreePtr<Public>(new Public); 01379 break; 01380 default: 01381 ASSERTFAIL("Invalid access specfier"); 01382 return TreePtr<Public>(new Public); 01383 break; 01384 } 01385 } 01386 01387 virtual DeclTy *ActOnCXXMemberDeclarator(clang::Scope *S, clang::AccessSpecifier AS, 01388 clang::Declarator &D, ExprTy *BitfieldWidth, 01389 ExprTy *Init, DeclTy *LastInGroup) 01390 { 01391 const clang::DeclSpec &DS = D.getDeclSpec(); 01392 TRACE("Element %p\n", Init); 01393 TreePtr<Declaration> d = CreateDelcaration( S, D, ConvertAccess( AS ) ); 01394 TreePtr<Instance> o = dynamic_pointer_cast<Instance>(d); 01395 01396 if( BitfieldWidth ) 01397 { 01398 ASSERT( o )( "only Instances may be bitfields" ); 01399 TreePtr<Integral> n( dynamic_pointer_cast<Integral>( o->type ) ); 01400 ASSERT( n )( "cannot specify width of non-numeric type" ); 01401 TreePtr<Expression> ee = hold_expr.FromRaw(BitfieldWidth); 01402 TreePtr<Literal> ll = dynamic_pointer_cast<Literal>(ee); 01403 ASSERT(ll )( "bitfield width must be literal, not expression"); // TODO evaluate 01404 TreePtr<SpecificInteger> ii = dynamic_pointer_cast<SpecificInteger>(ll); 01405 ASSERT(ll )( "bitfield width must be integer"); 01406 n->width = ii; 01407 } 01408 01409 if( Init ) 01410 { 01411 ASSERT( o )( "only Instances may have initialisers"); 01412 o->initialiser = hold_expr.FromRaw( Init ); 01413 } 01414 01415 IssueDeclaration( S, d ); 01416 return hold_decl.ToRaw( d ); 01417 } 01418 01419 virtual DeclTy *ActOnTag(clang::Scope *S, unsigned TagType, TagKind TK, 01420 clang::SourceLocation KWLoc, const clang::CXXScopeSpec &SS, 01421 clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, 01422 clang::AttributeList *Attr, 01423 MultiTemplateParamsArg TemplateParameterLists) 01424 { 01425 //ASSERT( !FromCXXScope(&SS) && "We're not doing anything with the C++ scope"); // TODO do something with the C++ scope 01426 // Now we're using it to link up with forward decls eg class foo { struct s; }; struct foo::s { blah } TODO is this even legal C++? 01427 01428 TRACE("Tag type %d, kind %d\n", TagType, (int)TK); 01429 ident_track.SeenScope( S ); 01430 01431 // TagType is an instance of DeclSpec::TST, indicating what kind of tag this 01432 // is (struct/union/enum/class). 01433 01434 // Proceed based on the context around the tag 01435 if( TK == clang::Action::TK_Reference ) 01436 { 01437 // Tag is a reference, that is a usage rather than a definition. We therefore 01438 // expect to be able to find a previous definition/declaration for it. Recurse 01439 // the search through enclosing scopes until we find it. 01440 TreePtr<Declaration> ed = FindExistingDeclaration( SS, Name, true ); 01441 ASSERT(ed)("Cannot find declaration of \"%s\"", Name->getName()); 01442 01443 return hold_decl.ToRaw( ed ); 01444 } 01445 01446 // Tag is a definition or declaration. Create if it doesn't already 01447 // exist, *but* don't recurse into enclosing scopes. 01448 if( TreePtr<Declaration> ed = FindExistingDeclaration( SS, Name, false ) ) 01449 { 01450 // Note: members will be filled in later, so nothing to do here 01451 // even if the is the "complete" version of the record (=definition). 01452 return hold_decl.ToRaw( ed ); 01453 } 01454 01455 TreePtr<Record> h; 01456 switch( (clang::DeclSpec::TST)TagType ) 01457 { 01458 case clang::DeclSpec::TST_union: 01459 h = TreePtr<Union>(new Union); 01460 break; 01461 case clang::DeclSpec::TST_struct: 01462 h = TreePtr<Struct>(new Struct); 01463 break; 01464 case clang::DeclSpec::TST_class: 01465 h = TreePtr<Class>(new Class); 01466 break; 01467 case clang::DeclSpec::TST_enum: 01468 h = TreePtr<Enum>(new Enum); 01469 break; 01470 default: 01471 ASSERTFAIL("Unknown type spec type"); 01472 break; 01473 } 01474 all_decls->members.insert(h); 01475 01476 if(Name) 01477 { 01478 h->identifier = CreateTypeIdentifier(Name); 01479 ident_track.Add(Name, h, S); 01480 } 01481 else 01482 { 01483 // TODO make a general-lurpose anon name generator 01484 char an[20]; 01485 static int ac=0; 01486 sprintf( an, "__anon%d", ac++ ); 01487 h->identifier = CreateTypeIdentifier(an); 01488 ident_track.Add(NULL, h, S); 01489 } 01490 01491 //TODO should we do something with TagKind? Maybe needed for render. 01492 //TODO use the attibutes 01493 01494 // struct/class/union pushed by ActOnFinishCXXClassDef() 01495 if( (clang::DeclSpec::TST)TagType == clang::DeclSpec::TST_enum ) 01496 decl_to_insert = h; 01497 01498 TRACE("done tag %p\n", h.get()); 01499 01500 return hold_decl.ToRaw( h ); 01501 } 01502 01503 /// ActOnStartCXXClassDef - This is called at the start of a class/struct/union 01504 /// definition, when on C++. 01505 virtual void ActOnStartCXXClassDef(clang::Scope *S, DeclTy *TagDecl, 01506 clang::SourceLocation LBrace) 01507 { 01508 TRACE("S%p\n", S); 01509 01510 // Just populate the members container for the Record node 01511 // we already created. No need to return anything. 01512 TreePtr<Declaration> d = hold_decl.FromRaw( TagDecl ); 01513 TreePtr<Record> h = dynamic_pointer_cast<Record>(d); 01514 01515 // We're about to populate the Record; if it has been populated already 01516 // then something's wrong 01517 ASSERT( h->members.empty() )("Record has already been defined"); 01518 01519 ident_track.SetNextRecord( h ); 01520 01521 inferno_scope_stack.push( h ); // decls for members will go on this scope 01522 backing_ordering[inferno_scope_stack.top()].clear(); 01523 } 01524 01525 /// ActOnFinishCXXClassDef - This is called when a class/struct/union has 01526 /// completed parsing, when on C++. 01527 virtual void ActOnFinishCXXClassDef(DeclTy *TagDecl) 01528 { 01529 TRACE(); 01530 01531 inferno_scope_stack.pop(); // class scope is complete 01532 ident_track.SetNextRecord(); 01533 01534 // TODO are structs etc definable in functions? If so, this will put the decl outside the function 01535 TreePtr<Declaration> d = hold_decl.FromRaw( TagDecl ); 01536 TreePtr<Record> h = dynamic_pointer_cast<Record>(d); 01537 decl_to_insert = h; 01538 } 01539 01540 virtual ExprResult ActOnMemberReferenceExpr(clang::Scope *S, ExprTy *Base, 01541 clang::SourceLocation OpLoc, 01542 clang::tok::TokenKind OpKind, 01543 clang::SourceLocation MemberLoc, 01544 clang::IdentifierInfo &Member) 01545 { 01546 TRACE("kind %d\n", OpKind); 01547 TreePtr<Lookup> a( new Lookup ); 01548 01549 // Turn -> into * and . 01550 if( OpKind == clang::tok::arrow ) // Base->Member 01551 01552 { 01553 TreePtr<Dereference> ou( new Dereference ); 01554 ou->operands.push_back( hold_expr.FromRaw( Base ) ); 01555 a->base = ou; 01556 } 01557 else if( OpKind == clang::tok::period ) // Base.Member 01558 01559 { 01560 a->base = hold_expr.FromRaw( Base ); 01561 } 01562 else 01563 { 01564 ASSERTFAIL("Unknown token accessing member"); 01565 } 01566 01567 // Find the specified member in the record implied by the expression on the left of . 01568 TreePtr<Node> tbase = TypeOf::instance( all_decls, a->base ); 01569 TreePtr<TypeIdentifier> tibase = dynamic_pointer_cast<TypeIdentifier>(tbase); 01570 ASSERT( tibase ); 01571 TreePtr<Record> rbase = GetRecordDeclaration(all_decls, tibase); 01572 ASSERT( rbase )( "thing on left of ./-> is not a record/record ptr" ); 01573 TreePtr<Instance> m = FindMemberByName( all_decls, rbase, string(Member.getName()) ); 01574 ASSERT(m)("in r.m or (&r)->m, could not find m in r\n" 01575 "m is %s, r is ", 01576 Member.getName()) 01577 (*rbase) 01578 (" named ") 01579 (*tibase); 01580 01581 a->member = m->identifier; 01582 01583 return hold_expr.ToRaw( a ); 01584 } 01585 01586 virtual ExprResult ActOnArraySubscriptExpr(clang::Scope *S, 01587 ExprTy *Base, clang::SourceLocation LLoc, 01588 ExprTy *Idx, clang::SourceLocation RLoc) 01589 { 01590 TreePtr<Subscript> su( new Subscript ); 01591 su->operands.push_back( hold_expr.FromRaw( Base ) ); 01592 su->operands.push_back( hold_expr.FromRaw( Idx ) ); 01593 return hold_expr.ToRaw( su ); 01594 } 01595 01596 /// ActOnCXXBoolLiteral - Parse {true,false} literals. 01597 virtual ExprResult ActOnCXXBoolLiteral(clang::SourceLocation OpLoc, 01598 clang::tok::TokenKind Kind) //TODO not working - get node has no info 01599 01600 { 01601 TreePtr<Literal> ic; 01602 TRACE("true/false tk %d %d %d\n", Kind, clang::tok::kw_true, clang::tok::kw_false ); 01603 01604 if(Kind == clang::tok::kw_true) 01605 ic = MakeTreePtr<True>(); 01606 else 01607 ic = MakeTreePtr<False>(); 01608 return hold_expr.ToRaw( ic ); 01609 } 01610 01611 virtual ExprResult ActOnCastExpr(clang::SourceLocation LParenLoc, TypeTy *Ty, 01612 clang::SourceLocation RParenLoc, ExprTy *Op) 01613 { 01614 TreePtr<Cast> c(new Cast); 01615 c->operand = hold_expr.FromRaw( Op ); 01616 c->type = hold_type.FromRaw( Ty ); 01617 return hold_expr.ToRaw( c ); 01618 } 01619 01620 virtual OwningStmtResult ActOnNullStmt(clang::SourceLocation SemiLoc) 01621 { 01622 TRACE(); 01623 TreePtr<Nop> n(new Nop); 01624 return ToStmt( n ); 01625 } 01626 01627 virtual ExprResult ActOnCharacterConstant(const clang::Token &tok) 01628 { 01629 string t = preprocessor.getSpelling(tok); 01630 01631 clang::CharLiteralParser literal(t.c_str(), t.c_str()+t.size(), tok.getLocation(), preprocessor); 01632 01633 if (literal.hadError()) 01634 return ExprResult(true); 01635 01636 llvm::APSInt rv(TypeDb::char_bits, !TypeDb::char_default_signed); 01637 rv = literal.getValue(); 01638 TreePtr<SpecificInteger> nc( new SpecificInteger(rv) ); 01639 01640 return hold_expr.ToRaw( nc ); 01641 } 01642 01643 virtual ExprResult ActOnInitList(clang::SourceLocation LParenLoc, 01644 ExprTy **InitList, unsigned NumInit, 01645 clang::InitListDesignations &Designators, 01646 clang::SourceLocation RParenLoc) 01647 { 01648 ASSERT( !Designators.hasAnyDesignators() )( "Designators in init lists unsupported" ); 01649 // Assume initialiser is for an Array, and create an ArrayInitialiser node 01650 // even if it's really a struct init. We'll come along later and replace with a 01651 // RecordInitialiser when we can see what the struct is. 01652 TreePtr<MakeArray> ao(new MakeArray); 01653 for(int i=0; i<NumInit; i++) 01654 { 01655 TreePtr<Expression> e = hold_expr.FromRaw( InitList[i] ); 01656 ao->operands.push_back( e ); 01657 } 01658 return hold_expr.ToRaw( ao ); 01659 } 01660 01661 // Create a RecordInitialiser using the elements of the supplied ArrayInitialiser and matching 01662 // them against the members of the supplied record. Records are stored using an unordered 01663 // collection for the members, so we have to use the ordered backing map. Array inits are ordered. 01664 TreePtr<MakeRecord> CreateRecordLiteralFromArrayLiteral( TreePtr<MakeArray> ai, 01665 TreePtr<Record> r ) 01666 { 01667 // Make new record initialiser and fill in the type 01668 TreePtr<MakeRecord> ri( new MakeRecord ); 01669 ri->type = r->identifier; 01670 01671 // Fill in the RecordLiteral operands collection with pairs that relate operands to their member ids 01672 TreePtr<Scope> s = r; 01673 PopulateMapOperator( ri, ai->operands, s ); 01674 01675 return ri; 01676 } 01677 01678 // Populate a map operator using elements from a sequence of expressions 01679 void PopulateMapOperator( TreePtr<MapOperator> mapop, // MapOperands corresponding to the elements of ai go in here 01680 Sequence<Expression> &seq, // Operands to insert, ordered as per the input program 01681 TreePtr<Scope> scope ) // Original Scope that established ordering, must be in backing_ordering 01682 01683 { 01684 // Get a reference to the ordered list of members for this scope from a backing list 01685 ASSERT( backing_ordering.IsExist(scope) )("Supplied scope did not make it into the backing ordering list"); 01686 Sequence<Declaration> &scope_ordered = backing_ordering[scope]; 01687 TRACE("%p %p\n", &scope->members, scope.get()); 01688 01689 // Go over the entire scope, keeping track of where we are in the Sequence 01690 int seq_index=0; // TODO rename 01691 FOREACH( TreePtr<Declaration> d, scope_ordered ) 01692 { 01693 if( seq_index == seq.size() ) 01694 { 01695 TRACE("Early out due to fewer elements in sequence than scope\n"); 01696 break; 01697 } 01698 // We only care about instances... 01699 if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>( d ) ) 01700 { 01701 // ...and not function instances 01702 if( !dynamic_pointer_cast<Callable>( i->type ) ) 01703 { 01704 // Get value out of array init and put it in record init together with member instance id 01705 TreePtr<Expression> v = seq[seq_index]; 01706 TreePtr<MapOperand> mi( new MapOperand ); 01707 mi->identifier = i->identifier; 01708 mi->value = v; 01709 mapop->operands.insert( mi ); 01710 01711 seq_index++; 01712 } 01713 } 01714 } 01715 ASSERT( seq_index == seq.size() ) 01716 ("Too many arguments to function/struct init (we allow too few for poor mans overlading, but not too many)\n") 01717 ("Scope was ")(*scope)(" for map operator ")(mapop)("\n"); 01718 } 01719 01720 TreePtr<String> CreateString( const char *s ) 01721 { 01722 TreePtr<SpecificString> st( new SpecificString(s) ); 01723 return st; 01724 } 01725 01726 TreePtr<String> CreateString( clang::IdentifierInfo *Id ) 01727 { 01728 return CreateString( Id->getName() ); 01729 } 01730 01731 /// ActOnStringLiteral - The specified tokens were lexed as pasted string 01732 /// fragments (e.g. "foo" "bar" L"baz"). 01733 virtual ExprResult ActOnStringLiteral(const clang::Token *Toks, unsigned NumToks) 01734 { 01735 clang::StringLiteralParser literal(Toks, NumToks, preprocessor, target_info); 01736 if (literal.hadError) 01737 return ExprResult(true); 01738 01739 return hold_expr.ToRaw( CreateString( literal.GetString() ) ); 01740 } 01741 01742 /// ActOnCXXThis - Parse the C++ 'this' pointer. 01743 virtual ExprResult ActOnCXXThis(clang::SourceLocation ThisLoc) 01744 { 01745 return hold_expr.ToRaw( TreePtr<This>( new This ) ); 01746 } 01747 01748 virtual DeclTy *ActOnEnumConstant(clang::Scope *S, DeclTy *EnumDecl, 01749 DeclTy *LastEnumConstant, 01750 clang::SourceLocation IdLoc, clang::IdentifierInfo *Id, 01751 clang::SourceLocation EqualLoc, ExprTy *Val) 01752 { 01753 TreePtr<Declaration> d( hold_decl.FromRaw( EnumDecl ) ); 01754 TreePtr<Enum> e( dynamic_pointer_cast<Enum>(d) ); 01755 TreePtr<Static> o(new Static()); 01756 all_decls->members.insert(o); 01757 o->identifier = CreateInstanceIdentifier(Id); 01758 o->constancy = MakeTreePtr<Const>(); // static const member need not consume storage!! 01759 o->type = e->identifier;//CreateIntegralType( TypeDb::integral_bits[clang::DeclSpec::TSW_unspecified], false ); 01760 if( Val ) 01761 { 01762 o->initialiser = hold_expr.FromRaw( Val ); 01763 } 01764 else if( LastEnumConstant ) 01765 { 01766 TreePtr<Declaration> lastd( hold_decl.FromRaw( LastEnumConstant ) ); 01767 TreePtr<Instance> lasto( dynamic_pointer_cast<Instance>(lastd) ); 01768 ASSERT(lasto)( "unexpected kind of declaration inside an enum"); 01769 TreePtr<Add> inf( new Add ); 01770 TreePtr<Expression> ei = lasto->identifier; 01771 inf->operands.insert( ei ); 01772 inf->operands.insert( CreateNumericConstant( 1 ) ); 01773 o->initialiser = inf; 01774 } 01775 else 01776 { 01777 o->initialiser = CreateNumericConstant( 0 ); 01778 } 01779 ident_track.Add(Id, o, S); 01780 return hold_decl.ToRaw( o ); 01781 } 01782 01783 virtual void ActOnEnumBody(clang::SourceLocation EnumLoc, DeclTy *EnumDecl, 01784 DeclTy **Elements, unsigned NumElements) 01785 { 01786 TreePtr<Declaration> d( hold_decl.FromRaw( EnumDecl ) ); 01787 TreePtr<Enum> e( dynamic_pointer_cast<Enum>(d) ); 01788 ASSERT( e )( "expected the declaration to be an enum"); 01789 for( int i=0; i<NumElements; i++ ) 01790 e->members.insert( hold_decl.FromRaw( Elements[i] ) ); 01791 } 01792 01793 /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with 01794 /// no declarator (e.g. "struct foo;") is parsed. 01795 virtual DeclTy *ParsedFreeStandingDeclSpec(clang::Scope *S, clang::DeclSpec &DS) 01796 { 01797 TRACE(); 01798 TreePtr<Declaration> d( hold_decl.FromRaw( DS.getTypeRep() ) ); 01799 TreePtr<Record> h( dynamic_pointer_cast<Record>( d ) ); 01800 ASSERT( h ); 01801 if( decl_to_insert ) 01802 { 01803 d = decl_to_insert; 01804 decl_to_insert = TreePtr<Declaration>(); 01805 } 01806 01807 // See if the declaration is already there (due to forwarding using 01808 // incomplete struct). If so, do not add it again 01809 Collection<Declaration> &sd = inferno_scope_stack.top()->members; 01810 FOREACH( const TreePtr<Declaration> &p, sd ) // TODO find()? 01811 if( TreePtr<Declaration>(p) == d ) 01812 return hold_decl.ToRaw( d ); 01813 01814 inferno_scope_stack.top()->members.insert( d ); 01815 backing_ordering[inferno_scope_stack.top()].push_back( d ); 01816 return hold_decl.ToRaw( d ); 01817 } 01818 01819 virtual ExprResult 01820 ActOnSizeOfAlignOfExpr( clang::SourceLocation OpLoc, bool isSizeof, bool isType, 01821 void *TyOrEx, const clang::SourceRange &ArgRange) 01822 { 01823 TreePtr<TypeOperator> p; 01824 if( isSizeof ) 01825 p = TreePtr<SizeOf>(new SizeOf); 01826 else 01827 p = TreePtr<AlignOf>(new AlignOf); 01828 01829 if( isType ) 01830 p->operand = hold_type.FromRaw(TyOrEx); 01831 else 01832 { 01833 ASSERT(0)("typeof() only supported on types at the moment"); 01834 // TODO THis is wrong because we'll get 2 refs to the type, need to duplicate, 01835 // or maybe add an alternative node and convert in a S&R 01836 p->operand = TreePtr<Type>::DynamicCast( TypeOf::instance( all_decls, hold_expr.FromRaw(TyOrEx) ) ); 01837 } 01838 return hold_expr.ToRaw( p ); 01839 } 01840 01841 virtual BaseResult ActOnBaseSpecifier(DeclTy *classdecl, 01842 clang::SourceRange SpecifierRange, 01843 bool Virt, clang::AccessSpecifier AccessSpec, 01844 TypeTy *basetype, 01845 clang::SourceLocation BaseLoc) 01846 { 01847 TreePtr<Type> t( hold_type.FromRaw( basetype ) ); 01848 TreePtr<SpecificTypeIdentifier> ti = dynamic_pointer_cast<SpecificTypeIdentifier>(t); 01849 ASSERT( ti ); 01850 TreePtr<Declaration> d = hold_decl.FromRaw( classdecl ); 01851 TreePtr<Record> r = dynamic_pointer_cast<Record>( d ); 01852 ASSERT( r ); 01853 01854 TreePtr<Base> base( new Base ); 01855 base->record = ti; 01856 /* if( Virt ) 01857 base->storage = MakeTreePtr<Virtual>(); 01858 else 01859 base->storage = MakeTreePtr<NonStatic>(); 01860 base->constancy = MakeTreePtr<NonConst>(); */ 01861 base->access = ConvertAccess( AccessSpec, r ); 01862 return hold_base.ToRaw( base ); 01863 } 01864 01865 virtual void ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases, 01866 unsigned NumBases) 01867 { 01868 TreePtr<Declaration> cd( hold_decl.FromRaw( ClassDecl ) ); 01869 TreePtr<InheritanceRecord> ih( dynamic_pointer_cast<InheritanceRecord>(cd) ); 01870 ASSERT( ih ); 01871 01872 for( int i=0; i<NumBases; i++ ) 01873 { 01874 ih->bases.insert( hold_base.FromRaw( Bases[i] ) ); 01875 } 01876 } 01877 01878 /// ActOnCXXNestedNameSpecifier - Called during parsing of a 01879 /// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now 01880 /// we want to resolve "bar::". 'SS' is empty or the previously parsed 01881 /// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar', 01882 /// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'. 01883 /// Returns a CXXScopeTy* object representing the C++ scope. 01884 virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(clang::Scope *S, 01885 const clang::CXXScopeSpec &SS, 01886 clang::SourceLocation IdLoc, 01887 clang::SourceLocation CCLoc, 01888 clang::IdentifierInfo &II) 01889 { 01890 TreePtr<Node> n( ident_track.Get( &II, FromCXXScope( &SS ) ) ); 01891 01892 return hold_scope.ToRaw( n ); 01893 } 01894 01895 /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the 01896 /// global scope ('::'). 01897 virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(clang::Scope *S, 01898 clang::SourceLocation CCLoc) 01899 { 01900 return hold_scope.ToRaw( global_scope ); 01901 } 01902 01903 /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global 01904 /// scope or nested-name-specifier) is parsed, part of a declarator-id. 01905 /// After this method is called, according to [C++ 3.4.3p3], names should be 01906 /// looked up in the declarator-id's scope, until the declarator is parsed and 01907 /// ActOnCXXExitDeclaratorScope is called. 01908 /// The 'SS' should be a non-empty valid CXXScopeSpec. 01909 virtual void ActOnCXXEnterDeclaratorScope(clang::Scope *S, const clang::CXXScopeSpec &SS) 01910 { 01911 TRACE(); 01912 TreePtr<Node> n = FromCXXScope( &SS ); 01913 ASSERT(n); 01914 ident_track.PushScope( NULL, n ); 01915 } 01916 01917 /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously 01918 /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same 01919 /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. 01920 /// Used to indicate that names should revert to being looked up in the 01921 /// defining scope. 01922 virtual void ActOnCXXExitDeclaratorScope(clang::Scope *S, const clang::CXXScopeSpec &SS) 01923 { 01924 TRACE(); 01925 ident_track.PopScope( NULL ); 01926 } 01927 01928 TreePtr<Instance> GetConstructor( TreePtr<Type> t ) 01929 { 01930 TreePtr<TypeIdentifier> id = dynamic_pointer_cast<TypeIdentifier>(t); 01931 ASSERT(id); 01932 TreePtr<Record> r = GetRecordDeclaration( all_decls, id ); 01933 01934 FOREACH( TreePtr<Declaration> d, r->members ) 01935 { 01936 TreePtr<Instance> o( dynamic_pointer_cast<Instance>(d) ); 01937 if( !o ) 01938 continue; 01939 if( dynamic_pointer_cast<Constructor>(o->type) ) 01940 return o; 01941 } 01942 ASSERTFAIL("missing constructor"); 01943 } 01944 01945 virtual MemInitResult ActOnMemInitializer( DeclTy *ConstructorDecl, 01946 clang::Scope *S, 01947 clang::IdentifierInfo *MemberOrBase, 01948 clang::SourceLocation IdLoc, 01949 clang::SourceLocation LParenLoc, 01950 ExprTy **Args, unsigned NumArgs, 01951 clang::SourceLocation *CommaLocs, 01952 clang::SourceLocation RParenLoc ) 01953 { 01954 // Get (or make) the constructor we're invoking 01955 TreePtr<Node> n = ident_track.Get( MemberOrBase ); 01956 TreePtr<Instance> om( dynamic_pointer_cast<Instance>(n) ); 01957 ASSERT( om ); 01958 TreePtr<Instance> cm = GetConstructor( om->type ); 01959 ASSERT( cm ); 01960 ASSERT( cm->identifier ); 01961 01962 // Build a lookup to the constructor, using the speiciifed subobject and the matching constructor 01963 TreePtr<Lookup> lu(new Lookup); 01964 lu->base = om->identifier; 01965 lu->member = cm->identifier; 01966 01967 // Build a call to the constructor with supplied args 01968 Sequence<Expression> args; 01969 CollectArgs( &args, Args, NumArgs ); 01970 TreePtr<Call> call = CreateCall( args, lu ); 01971 01972 // Get the constructor whose init list we're adding to (may need to start a 01973 // new compound statement) 01974 TreePtr<Declaration> d( hold_decl.FromRaw( ConstructorDecl ) ); 01975 TreePtr<Instance> o( dynamic_pointer_cast<Instance>(d) ); 01976 ASSERT(o); 01977 TreePtr<Compound> comp = dynamic_pointer_cast<Compound>(o->initialiser); 01978 if( !comp ) 01979 { 01980 comp = TreePtr<Compound>( new Compound ); 01981 o->initialiser = comp; 01982 TRACE(); 01983 } 01984 01985 // Add it 01986 comp->statements.push_back( call ); 01987 return 0; 01988 } 01989 01990 void CollectArgs( Sequence<Expression> *ps, ExprTy **Args, unsigned NumArgs ) 01991 { 01992 for(int i=0; i<NumArgs; i++ ) 01993 ps->push_back( hold_expr.FromRaw(Args[i]) ); 01994 } 01995 01996 /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the 01997 /// new was qualified (::new). In a full new like 01998 /// @code new (p1, p2) type(c1, c2) @endcode 01999 /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2 02000 /// expressions in ConstructorArgs. The type is passed as a declarator. 02001 virtual ExprResult ActOnCXXNew( clang::SourceLocation StartLoc, bool UseGlobal, 02002 clang::SourceLocation PlacementLParen, 02003 ExprTy **PlacementArgs, unsigned NumPlaceArgs, 02004 clang::SourceLocation PlacementRParen, 02005 bool ParenTypeId, clang::Declarator &D, 02006 clang::SourceLocation ConstructorLParen, 02007 ExprTy **ConstructorArgs, unsigned NumConsArgs, 02008 clang::SourceLocation ConstructorRParen ) 02009 { 02010 TreePtr<New> n( new New ); 02011 n->type = CreateTypeNode( D ); 02012 CollectArgs( &(n->placement_arguments), PlacementArgs, NumPlaceArgs ); 02013 CollectArgs( &(n->constructor_arguments), ConstructorArgs, NumConsArgs ); 02014 02015 if( UseGlobal ) 02016 n->global = TreePtr<Global>( new Global ); 02017 else 02018 n->global = TreePtr<NonGlobal>( new NonGlobal ); 02019 02020 // TODO cant figure out meaning of ParenTypeId 02021 02022 return hold_expr.ToRaw( n ); 02023 } 02024 02025 /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if 02026 /// the delete was qualified (::delete). ArrayForm is true if the array form 02027 /// was used (delete[]). 02028 virtual ExprResult ActOnCXXDelete( clang::SourceLocation StartLoc, bool UseGlobal, 02029 bool ArrayForm, ExprTy *Expression ) 02030 { 02031 TreePtr<Delete> d( new Delete ); 02032 d->pointer = hold_expr.FromRaw( Expression ); 02033 02034 if( ArrayForm ) 02035 d->array = TreePtr<DeleteArray>( new DeleteArray ); 02036 else 02037 d->array = TreePtr<DeleteNonArray>( new DeleteNonArray ); 02038 02039 if( UseGlobal ) 02040 d->global = TreePtr<Global>( new Global ); 02041 else 02042 d->global = TreePtr<NonGlobal>( new NonGlobal ); 02043 02044 return hold_expr.ToRaw( d ); 02045 } 02046 02047 virtual ExprResult ActOnCompoundLiteral(clang::SourceLocation LParen, TypeTy *Ty, 02048 clang::SourceLocation RParen, ExprTy *Op) 02049 { 02050 TreePtr<Type> t = hold_type.FromRaw( Ty ); 02051 TreePtr<Expression> e = hold_expr.FromRaw( Op ); 02052 02053 TRACE("%p\n", t.get() ); 02054 02055 // At this point, when we have the instance (and hence the type) and the initialiser 02056 // we can detect when an array initialiser has been inserted for a record instance and 02057 // change it. 02058 if( TreePtr<MakeArray> ai = dynamic_pointer_cast<MakeArray>(e) ) 02059 if( TreePtr<TypeIdentifier> ti = dynamic_pointer_cast<TypeIdentifier>(t) ) 02060 if( TreePtr<Record> r = GetRecordDeclaration(all_decls, ti) ) 02061 e = CreateRecordLiteralFromArrayLiteral( ai, r ); 02062 02063 return hold_expr.ToRaw( e ); 02064 } 02065 02066 //--------------------------------------------- unimplemented actions ----------------------------------------------- 02067 // Note: only actions that return something (so we don't get NULL XTy going around the place). No obj-C or GCC 02068 // extensions. These all assert out immediately. 02069 02070 virtual DeclTy *ActOnFileScopeAsmDecl(clang::SourceLocation Loc, ExprArg AsmString) 02071 { 02072 ASSERTFAIL("Unimplemented action"); 02073 return 0; 02074 } 02075 02076 virtual DeclTy *ActOnField(clang::Scope *S, DeclTy *TagD, clang::SourceLocation DeclStart, 02077 clang::Declarator &D, ExprTy *BitfieldWidth) 02078 { 02079 ASSERTFAIL("Unimplemented action"); // TODO is this C-not-C++ or ObjC? 02080 return 0; 02081 } 02082 02083 virtual StmtResult ActOnAsmStmt(clang::SourceLocation AsmLoc, 02084 bool IsSimple, 02085 bool IsVolatile, 02086 unsigned NumOutputs, 02087 unsigned NumInputs, 02088 std::string *Names, 02089 ExprTy **Constraints, 02090 ExprTy **Exprs, 02091 ExprTy *AsmString, 02092 unsigned NumClobbers, 02093 ExprTy **Clobbers, 02094 clang::SourceLocation RParenLoc) 02095 { 02096 ASSERTFAIL("Unimplemented action"); 02097 return 0; 02098 } 02099 02100 virtual ExprResult ActOnPredefinedExpr(clang::SourceLocation Loc, 02101 clang::tok::TokenKind Kind) 02102 { 02103 ASSERTFAIL("Unimplemented action"); 02104 return 0; 02105 } 02106 02107 virtual DeclTy *ActOnStartNamespaceDef(clang::Scope *S, clang::SourceLocation IdentLoc, 02108 clang::IdentifierInfo *Ident, 02109 clang::SourceLocation LBrace) 02110 { 02111 ASSERTFAIL("Unimplemented action"); 02112 return 0; 02113 } 02114 02115 virtual ExprResult ActOnCXXNamedCast(clang::SourceLocation OpLoc, clang::tok::TokenKind Kind, 02116 clang::SourceLocation LAngleBracketLoc, TypeTy *Ty, 02117 clang::SourceLocation RAngleBracketLoc, 02118 clang::SourceLocation LParenLoc, ExprTy *Op, 02119 clang::SourceLocation RParenLoc) 02120 { 02121 ASSERTFAIL("Unimplemented action"); 02122 return 0; 02123 } 02124 02125 virtual ExprResult ActOnCXXThrow(clang::SourceLocation OpLoc, 02126 ExprTy *Op = 0) 02127 { 02128 ASSERTFAIL("Unimplemented action"); 02129 return 0; 02130 } 02131 02132 virtual ExprResult ActOnCXXTypeConstructExpr(clang::SourceRange TypeRange, 02133 TypeTy *TypeRep, 02134 clang::SourceLocation LParenLoc, 02135 ExprTy **Exprs, 02136 unsigned NumExprs, 02137 clang::SourceLocation *CommaLocs, 02138 clang::SourceLocation RParenLoc) 02139 { 02140 ASSERTFAIL("Unimplemented action"); 02141 return 0; 02142 } 02143 02144 virtual ExprResult ActOnCXXConditionDeclarationExpr(clang::Scope *S, 02145 clang::SourceLocation StartLoc, 02146 clang::Declarator &D, 02147 clang::SourceLocation EqualLoc, 02148 ExprTy *AssignExprVal) 02149 { 02150 ASSERTFAIL("Unimplemented action"); 02151 return 0; 02152 } 02153 02154 virtual DeclTy *ActOnExceptionDeclarator(clang::Scope *S, clang::Declarator &D) 02155 { 02156 ASSERTFAIL("Unimplemented action"); 02157 return 0; 02158 } 02159 02160 virtual OwningStmtResult ActOnCXXCatchBlock(clang::SourceLocation CatchLoc, 02161 DeclTy *ExceptionDecl, 02162 StmtArg HandlerBlock) 02163 { 02164 ASSERTFAIL("Unimplemented action"); 02165 return StmtEmpty(); 02166 } 02167 02168 virtual OwningStmtResult ActOnCXXTryBlock(clang::SourceLocation TryLoc, 02169 StmtArg TryBlock, 02170 MultiStmtArg Handlers) 02171 { 02172 ASSERTFAIL("Unimplemented action"); 02173 return StmtEmpty(); 02174 } 02175 /// ActOnUsingDirective - This is called when using-directive is parsed. 02176 virtual DeclTy *ActOnUsingDirective(clang::Scope *CurScope, 02177 clang::SourceLocation UsingLoc, 02178 clang::SourceLocation NamespcLoc, 02179 const clang::CXXScopeSpec &SS, 02180 clang::SourceLocation IdentLoc, 02181 clang::IdentifierInfo *NamespcName, 02182 clang::AttributeList *AttrList) 02183 { 02184 ASSERTFAIL("Unimplemented action"); 02185 return 0; 02186 } 02187 02188 /// ActOnParamUnparsedDefaultArgument - We've seen a default 02189 /// argument for a function parameter, but we can't parse it yet 02190 /// because we're inside a class definition. Note that this default 02191 /// argument will be parsed later. 02192 virtual void ActOnParamUnparsedDefaultArgument(DeclTy *param, 02193 clang::SourceLocation EqualLoc) 02194 { 02195 ASSERTFAIL("Unimplemented action"); 02196 } 02197 02198 /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of 02199 /// the default argument for the parameter param failed. 02200 virtual void ActOnParamDefaultArgumentError(DeclTy *param) 02201 { 02202 ASSERTFAIL("Unimplemented action"); 02203 } 02204 02205 virtual void ActOnEnumStartDefinition(clang::Scope *S, DeclTy *EnumDecl) 02206 { 02207 ASSERTFAIL("Unimplemented action"); 02208 } 02209 }; 02210 }; 02211 02212 #endif