Mercurial > hg > CbC > CbC_llvm
view tools/clang/lib/Parse/ParseCbC.cpp @ 63:0d1cf6cb7029
add comments for setTST
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 02 Feb 2014 20:10:53 +0900 |
parents | fe2728d9537d |
children | 0aa33659e8e4 |
line wrap: on
line source
#ifndef noCbC #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Lookup.h" #include "clang/Lex/LiteralSupport.h" #include "clang/AST/ASTConsumer.h" #include <sstream> #include <string> #include "CbCHelper.h" using namespace clang; /// The class which belong to this namespace is from other files' namespace. /// Because those namespaces are unnamed namespaces, we can't access them. /// So create this namespace and copy classes from those namespaces. namespace ExternalSpace { // from ParseExpr.cpp , ParseStmt.cpp class CastExpressionIdValidator : public CorrectionCandidateCallback { public: CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes) : AllowNonTypes(AllowNonTypes) { WantTypeSpecifiers = AllowTypes; } virtual bool ValidateCandidate(const TypoCorrection &candidate) { NamedDecl *ND = candidate.getCorrectionDecl(); if (!ND) return candidate.isKeyword(); if (isa<TypeDecl>(ND)) return WantTypeSpecifiers; return AllowNonTypes; } private: bool AllowNonTypes; }; class StatementFilterCCC : public CorrectionCandidateCallback { public: StatementFilterCCC(Token nextTok) : NextToken(nextTok) { WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) || nextTok.is(tok::identifier) || nextTok.is(tok::star) || nextTok.is(tok::amp) || nextTok.is(tok::l_square); WantExpressionKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::identifier) || nextTok.is(tok::arrow) || nextTok.is(tok::period); WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) || nextTok.is(tok::identifier) || nextTok.is(tok::l_brace); WantCXXNamedCasts = false; } virtual bool ValidateCandidate(const TypoCorrection &candidate) { if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>()) return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD); if (NextToken.is(tok::equal)) return candidate.getCorrectionDeclAs<VarDecl>(); if (NextToken.is(tok::period) && candidate.getCorrectionDeclAs<NamespaceDecl>()) return false; return CorrectionCandidateCallback::ValidateCandidate(candidate); } private: Token NextToken; }; } /// Prepare__retForGotoWithTheEnvExpr - Prepare __CbC_return, code segment for returning and some necessary statements. /// It is called when the parser find __return and statements are put into complex statement. /// /// examples which are created: /// complex statement: /// ({ /// __code (*__CbC_return)(return_type, void*); /// __CbC_return = code_segment_for_return; /// __CbC_return; /// }); /// code segment: /// __code ret(return_type retval, void *env){ /// *(return_type)((struct CbC_environment *)(env))->ret_p = n; /// longjmp((int*)(((struct __CbC_environment *)env)->env),1); /// } ExprResult Parser::Prepare__retForGotoWithTheEnvExpr(){ StmtResult innerRes; SourceLocation Loc = Tok.getLocation(); IdentifierInfo *__CbC_retII = CreateIdentifierInfo(__CBC_RETURN_NAME, Loc); IdentifierInfo *retcsII = CreateUniqueIdentifierInfo(__CBC_RET_CODE_BASE_NAME, Loc); Create__CbC_envStruct(Loc, AS_none); Actions.ActOnStartStmtExpr(); StmtResult CompoundStmtRes; ParseScope CompoundScope(this, Scope::DeclScope); PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),Loc,"in compound statement ('{}')"); StmtVector CompoundStmts; // create code segment for return to C's function if (CreateRetCS()) { // error check : function type is void or not. Diag(Tok, diag::err_cannot_use_goto_with_env); return ExprError(); } // __code (*__CbC_return)(); innerRes = CreateDeclStmt(__CbC_retII, true, false, DeclSpec::TST___code); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // __CbC_return = ret; innerRes = CreateAssignmentStmt(__CbC_retII, retcsII); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // __CbC_return; innerRes = CreateComplexStmtRet(__CbC_retII, false); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); ConsumeToken(); // eat the '__return'. return Actions.ActOnStmtExpr(Loc, CompoundStmtRes.take(), Loc); } /// Prepare__envForGotoWithTheEnvExpr - Prepare __CbC_environment, struct __CbC_env and some necessary statements. /// It is called when the parser find __environment and statements are put into complex statement. /// /// examples which are created: /// complex statement: /// ({ /// struct __CbC_env __CbC_environment; /// jmp_buf env_buf; /// return_type retval; /// __CbC_environment.ret_p = &retval; /// __CbC_environment.env = &env_buf /// if (setjmp(__CbC_environment.env)){ /// return retval; /// } /// &__CbC_environment; /// }); /// struct __CbC_env: /// struct __CbC_env{ /// void *ret_p,*env; /// } ExprResult Parser::Prepare__envForGotoWithTheEnvExpr(){ StmtResult innerRes; SourceLocation Loc = Tok.getLocation(); IdentifierInfo *bufII = CreateUniqueIdentifierInfo(__CBC_BUF_NAME, Loc); IdentifierInfo *retvalII = CreateUniqueIdentifierInfo(__CBC_RETVAL_NAME, Loc); IdentifierInfo *structII = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc); IdentifierInfo *__CbC_envII = CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc); IdentifierInfo *envII = CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc); IdentifierInfo *ret_pII = CreateIdentifierInfo(__CBC_STRUCT_POINTER_NAME, Loc); Create__CbC_envStruct(Loc, AS_none); Actions.ActOnStartStmtExpr(); ParseScope CompoundScope(this, Scope::DeclScope); PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),Loc,"in compound statement ('{}')"); StmtVector CompoundStmts; // struct __CbC_env __CbC_environment; innerRes = CreateDeclStmt(__CbC_envII, false, false, DeclSpec::TST_struct, structII); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // returnType retval; innerRes = CreateDeclStmt(retvalII, false, true); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // jmp_buf env_buf; innerRes = CreateDeclStmt(bufII, false, false, DeclSpec::TST_typename, CreateIdentifierInfo("jmp_buf", Loc)); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // __CbC_environment.ret_p = &retval; innerRes = CreateAssignmentStmt(__CbC_envII, retvalII, true, true, ret_pII); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // __CbC_environment.env = env_buf; innerRes = CreateAssignmentStmt(__CbC_envII, bufII, true, false, envII); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // create statements of setjmp innerRes = CreateSjForContinuationWithTheEnv(); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); // __CbC_environment; innerRes = CreateComplexStmtRet(__CbC_envII, true); if (innerRes.isUsable()) CompoundStmts.push_back(innerRes.release()); StmtResult CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); ConsumeToken(); // eat the '__environment'. return Actions.ActOnStmtExpr(Loc, CompoundStmtRes.take(), Loc); } /// CreateAssignmentStmt - Create assignment statement such as "aaa = bbb;", "auaua = llll;", etc. /// It can create 4 kinds of statement. /// 1. common assignment statement: /// variable '=' variable ';' /// 2. LHS variable is member of struct: /// structVar '.' member '=' variable ';' /// 3. RHS variable is address of operand: /// variable '=' '&' variable ';' /// 4. 2+3: /// structVar '.' member '=' '&' variable ';' StmtResult Parser::CreateAssignmentStmt(IdentifierInfo* LHSII, IdentifierInfo* RHSII, bool LHSisMemberAccess, bool RHShasAmp, IdentifierInfo* extraLHSII, IdentifierInfo* extraRHSII){ ExprResult Expr,LHS,RHS; Token Next,LHSToken; SourceLocation Loc = Tok.getLocation(); CXXScopeSpec SS; Next.startToken(); Next.setKind(tok::period); LHSToken.startToken(); LHSToken.setLocation(Loc); LHSToken.setIdentifierInfo(LHSII); LHSToken.setKind(tok::annot_primary_expr); ExternalSpace::StatementFilterCCC Validator(Next); Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, LHSII, Loc, Next, false, SS.isEmpty() ? &Validator : 0); setExprAnnotation(LHSToken, Classification.getExpression()); LHSToken.setAnnotationEndLoc(Loc); PP.AnnotateCachedTokens(LHSToken); LHS = getExprAnnotation(LHSToken); if (LHSisMemberAccess) LHS = LookupMemberAndBuildExpr(extraLHSII, LHS.take(), false); RHS = LookupNameAndBuildExpr(RHSII); if (RHShasAmp) RHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::amp, RHS.get()); Expr = Actions.ActOnBinOp(getCurScope(), Loc,tok::equal,LHS.take(),RHS.take()); return Actions.ActOnExprStmt(Expr); } /// CreateDeclStmt - Create declaration statement such as "int aaa;". /// If isRetCS is true, create code segment for return to C's function. And Name is name of code segment. /// If copyType is true, type of variable is copied from callee. StmtResult Parser::CreateDeclStmt(IdentifierInfo *II, bool isRetCS, bool copyType, DeclSpec::TST valueType, IdentifierInfo* Name){ SourceLocation Loc = Tok.getLocation(); DeclGroupPtrTy DeclGPT; ParsingDeclSpec DS(*this); DeclSpec *DSp; DSp = &DS; setTST(&DS, valueType, Name); ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Declarator::BlockContext)); D.SetIdentifier(II, Loc); if (isRetCS) { D.setEllipsisLoc(SourceLocation()); bool hadGroupingParens = D.hasGroupingParens(); D.setGroupingParens(true); D.SetRangeEnd(Loc); DeclSpec FDS(AttrFactory); DS.Finish(Diags, PP); D.AddTypeInfo(DeclaratorChunk::getPointer(FDS.getTypeQualifiers(), Loc, FDS.getConstSpecLoc(), FDS.getVolatileSpecLoc(), FDS.getRestrictSpecLoc()), FDS.getAttributes(), SourceLocation()); D.setGroupingParens(hadGroupingParens); ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope| (D.isFunctionDeclaratorAFunctionDeclaration() ? Scope::FunctionDeclarationScope : 0)); bool HasProto = false; SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc; DeclSpec FPDS(AttrFactory); bool RefQualifierIsLValueRef = true; ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; ParmVarDecl *Param; FunctionDecl *CurFunctionDecl = Actions.getCurFunctionDecl(); QualType CurFuncResQT = CurFunctionDecl->getResultType(); TypeSourceInfo *CurFuncTI = Actions.Context.CreateTypeSourceInfo(CurFuncResQT); Param = CreateParam(); Param->setTypeSourceInfo(CurFuncTI); Param->setType(CurFuncResQT); ParamInfo.push_back(DeclaratorChunk::ParamInfo(0, Loc, Param, 0)); Param = CreateParam(0, 1, DeclSpec::TST_void); ParamInfo.push_back(DeclaratorChunk::ParamInfo(0, Loc, Param, 0)); HasProto = true; D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto,false,Loc,ParamInfo.data(), ParamInfo.size(),EllipsisLoc, Loc, FPDS.getTypeQualifiers(), RefQualifierIsLValueRef,RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc,SourceLocation(),ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(),DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0,Loc, Loc, D,TrailingReturnType), FnAttrs, Loc); PrototypeScope.Exit(); DSp = &FDS; } SmallVector<Decl *, 8> DeclsInGroup; Decl *FirstDecl; if (copyType) FirstDecl = HandleDeclAndChangeDeclType(D); else FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); D.complete(FirstDecl); DeclsInGroup.push_back(FirstDecl); DeclGPT = Actions.FinalizeDeclaratorGroup(getCurScope(), *DSp, DeclsInGroup); return Actions.ActOnDeclStmt(DeclGPT, Loc, Loc); } /// handleDeclAndChangeDeclType - This function imitated Parser::ParseDeclarationAfterDeclaratorAndAttributes() and Sema::ActOnDeclarator(). /// The origins get Type from Declarator but this function get Type from current function. /// It is useful for CbC to create statements for the continuation with the environments. Decl* Parser::HandleDeclAndChangeDeclType(Declarator &D) { D.setFunctionDefinitionKind(FDK_Declaration); DeclarationNameInfo NameInfo = Actions.GetNameForDeclarator(D); DeclContext *DC = Actions.CurContext; QualType R = Actions.getCurFunctionDecl()->getResultType(); // copy a type TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R); // copy a type infomation Scope *S = getCurScope(); LookupResult Previous(Actions, NameInfo, Actions.LookupOrdinaryName, Actions.ForRedeclaration); bool IsLinkageLookup = false; bool CreateBuiltins = false; // If the declaration we're planning to build will be a function // or object with linkage, then look for another declaration with // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). // // If the declaration we're planning to build will be declared with // external linkage in the translation unit, create any builtin with // the same name. if (R->isFunctionType()) { IsLinkageLookup = true; CreateBuiltins = Actions.CurContext->getEnclosingNamespaceContext()->isTranslationUnit(); } else if (Actions.CurContext->getRedeclContext()->isTranslationUnit()) CreateBuiltins = true; if (IsLinkageLookup) Previous.clear(Actions.LookupRedeclarationWithLinkage); Actions.LookupName(Previous, S, CreateBuiltins); // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); NamedDecl *New; bool AddToScope = true; if (R->isFunctionType()) { New = Actions.ActOnFunctionDeclarator(S, D, DC, TInfo, Previous, MultiTemplateParamsArg(), AddToScope); } else { New = Actions.ActOnVariableDeclarator(S, D, DC, TInfo, Previous, MultiTemplateParamsArg(), AddToScope); } if (New->getDeclName() && AddToScope) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl(); Actions.PushOnScopeChains(New, S, AddToContext); if (!AddToContext) Actions.CurContext->addHiddenDecl(New); } return New; } /// CreateSjForContinuationWithEnv - Create statements of setjmp for continuation with the environment. /// code example: /// if (setjmp(__CbC_environment.env)){ /// return retval; /// } StmtResult Parser::CreateSjForContinuationWithTheEnv(){ SourceLocation Loc = Tok.getLocation(); StmtResult IfRes; ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, true/* C99 or CXX */); ExprResult CondExp; Decl *CondVar = 0; CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("setjmp", Loc)); ExprVector ArgExprs; ExprResult __envExprRes = CondExp.get(); __envExprRes = LookupNameAndBuildExpr(CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc)); __envExprRes = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc), __envExprRes.take(), false); ArgExprs.push_back(__envExprRes.release()); CondExp = Actions.ActOnCallExpr(getCurScope(), CondExp.take(), Loc, ArgExprs, Loc, 0); CondExp = Actions.ActOnBooleanCondition(getCurScope(), Loc, CondExp.get()); FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), Loc)); ParseScope InnerScope(this, Scope::DeclScope,false); SourceLocation InnerStatementTrailingElseLoc; StmtResult StmtRes; ParseScope CompoundScope(this, Scope::DeclScope); PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),Loc,"in create setjmp statement for CbC"); StmtVector innerStmts; StmtResult innerStmtRes; ExprResult innerExprRes; innerExprRes = LookupNameAndBuildExpr(CreateUniqueIdentifierInfo(__CBC_RETVAL_NAME, Loc)); innerStmtRes = Actions.ActOnReturnStmt(Loc, innerExprRes.take()); if (innerStmtRes.isUsable()) innerStmts.push_back(innerStmtRes.release()); StmtRes = Actions.ActOnCompoundStmt(Loc, Loc,innerStmts, false); StmtResult ThenStmt(StmtRes); InnerScope.Exit(); IfScope.Exit(); StmtResult ElseStmt; IfRes = Actions.ActOnIfStmt(Loc, FullCondExp, CondVar, ThenStmt.get(),Loc, ElseStmt.get()); return IfRes; } /// LookupNameAndBuildExpr - Look up name, create ExprResult and return it. ExprResult Parser::LookupNameAndBuildExpr(IdentifierInfo *II, bool IsAddressOfOperand){ SourceLocation Loc = Tok.getLocation(); UnqualifiedId Name; CXXScopeSpec SS; SourceLocation TemplateKWLoc; ExternalSpace::CastExpressionIdValidator Validator(false,true); Name.setIdentifier(II, Loc); return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, false, IsAddressOfOperand, &Validator); } /// LookupNameAndBuildExpr - Look up member name, create ExprResult and return it. /// If IsArrow is true, the name is accessed by arrow operand. ExprResult Parser::LookupMemberAndBuildExpr(IdentifierInfo *II, Expr* Base, bool IsArrow){ SourceLocation Loc = Tok.getLocation(); ExprResult Res; CXXScopeSpec SS; UnqualifiedId Name; SourceLocation TemplateKWLoc; Name.setIdentifier(II,Loc); TemplateArgumentListInfo TemplateArgsBuffer; DeclarationNameInfo NameInfo; const TemplateArgumentListInfo *TemplateArgs; Actions.DecomposeUnqualifiedId(Name, TemplateArgsBuffer, NameInfo, TemplateArgs); Res = Actions.MaybeConvertParenListExprToParenExpr(getCurScope(), Base); Base = Res.take(); LookupResult R(Actions, NameInfo, Actions.LookupMemberName); ExprResult BaseResult = Actions.Owned(Base); Actions.LookupMemberExpr(R, BaseResult, IsArrow, Loc, SS, 0, TemplateArgs != 0); Base = BaseResult.take(); Sema::ActOnMemberAccessExtraArgs ExtraArgs = {getCurScope(), Name, 0, false}; return Actions.BuildMemberReferenceExpr(Base, Base->getType(), Loc, IsArrow, SS, TemplateKWLoc, 0, R, TemplateArgs,false, &ExtraArgs); } /// Create__CbC_envStruct - This method create "struct __CbC_env" which is used to continuation with environment. /// If the __CbC_env has been already defined, it doesn't create __CbC_env again. /// The example of struct which is created : /// struct __CbC_env{ /// void *ret_p,*env; /// }; void Parser::Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS) { IdentifierInfo *Name = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc); // Check previous definition. If the __CbC_env has been already defined, we have not to create again. LookupResult Previous(Actions, Name, Loc, Actions.LookupTagName, Actions.ForRedeclaration); if(Actions.LookupName(Previous, getCurScope())) return; Scope *SavedScope = getCurScope(); DeclContext *SavedContext = Actions.CurContext; sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val(); Actions.CurContext = static_cast<DeclContext *>(Actions.Context.getTranslationUnitDecl()); Scope *TopScope = getCurScope(); while(TopScope->getParent() != NULL) TopScope = TopScope->getParent(); Actions.CurScope = TopScope; ParsingDeclSpec SDS(*this); SDS.SetRangeStart(Loc); SDS.SetRangeEnd(Loc); DeclSpec::TST TagType = DeclSpec::TST_struct; DeclResult TagOrTempResult = true; bool Owned = false; bool IsDependent = false; ParsedAttributesWithRange attrs(AttrFactory); MultiTemplateParamsArg TParams; TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, Sema::TUK_Definition, Loc, SDS.getTypeSpecScope(), Name, Loc, attrs.getList(), AS, SDS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, clang::TypeResult()); Decl *TagDecl = TagOrTempResult.get(); PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, Loc, "parsing struct/union body"); ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); SmallVector<Decl *, 32> FieldDecls; const char *PrevSpec = 0; unsigned DiagID = 0; FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME)); FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_int, Loc, __CBC_STRUCT_ENV_NAME)); Actions.ActOnFields(getCurScope(),Loc, TagDecl, FieldDecls,Loc, Loc,attrs.getList()); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl,Loc); bool Result = SDS.SetTypeSpecType(TagType, Loc,Loc.isValid() ? Loc : Loc, PrevSpec, DiagID, TagOrTempResult.get(), Owned); if (Result){ Diag(Loc, DiagID) << PrevSpec; } SDS.Finish(Diags,PP); Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, SDS); SDS.complete(TheDecl); Actions.ConvertDeclToDeclGroup(TheDecl); Actions.CurScope = SavedScope; Actions.CurContext = SavedContext; Actions.FunctionScopes.push_back(SavedFSI); } /// Create__CbC_envBody - Create void type pointer ret_p and env which are member of __CbC_env. Decl* Parser::Create__CbC_envBody(Decl* TagDecl, DeclSpec::TST T, SourceLocation Loc, const char* Name){ ParsingDeclSpec PDS(*this); setTST(&PDS, T); SourceLocation CommaLoc; ParsingFieldDeclarator DeclaratorInfo(*this, PDS); DeclaratorInfo.D.setCommaLoc(CommaLoc); DeclaratorInfo.D.SetRangeEnd(Loc); DeclSpec DS(AttrFactory); DS.Finish(Diags,PP); DeclaratorInfo.D.SetIdentifier(CreateIdentifierInfo(Name, Loc),Loc); DeclaratorInfo.D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,DS.getConstSpecLoc(), DS.getVolatileSpecLoc(),DS.getRestrictSpecLoc()), DS.getAttributes(),SourceLocation()); Decl *Field = Actions.ActOnField(getCurScope(), TagDecl, DeclaratorInfo.D.getDeclSpec().getSourceRange().getBegin(), DeclaratorInfo.D, DeclaratorInfo.BitfieldSize); DeclaratorInfo.complete(Field); return Field; } /// CreateIdentifierInfo - Create IdentifierInfo from char pointer. /// usage : /// IdentifierInfo *II = CreateIdentifierInfo(IIName, Location); IdentifierInfo* Parser::CreateIdentifierInfo(const char* Name, SourceLocation Loc) { int length = strlen(Name); Token TokenForII; TokenForII.startToken(); TokenForII.setLocation(Loc); TokenForII.setLength(length); TokenForII.setKind(tok::raw_identifier); TokenForII.setRawIdentifierData(Name); IdentifierInfo *II; II = PP.getIdentifierInfo(StringRef(TokenForII.getRawIdentifierData(),TokenForII.getLength())); TokenForII.setIdentifierInfo(II); TokenForII.setKind(II->getTokenID()); return II; } /// CreateUniqueIdentifierInfo - Create unique IdentifierInfo. /// IdentifierInfos have unique name which were created by this function. /// Naming conventions is current function's name '..' variable name /// For example, if current function's name is 'main' and variable name is 'auaua', IdentifierInfo's name is 'main..auaua'. IdentifierInfo* Parser::CreateUniqueIdentifierInfo(const char* Name, SourceLocation Loc){ IdentifierInfo *II; std::ostringstream os; os << curFuncName << ".." /* separator */ << Name; II = CreateIdentifierInfo(os.str().c_str(), Loc); return II; } /// CreateRetCS - Create code segment which is used for continuation with the environment. /// create these codes: /// __code ret(return_type retval, void *env){ /// *(return_type)((struct CbC_environment *)(env))->ret_p = n; /// longjmp((int*)(((struct __CbC_environment *)env)->env),1); /// } bool Parser::CreateRetCS(){ FunctionDecl *CurFunctionDecl = Actions.getCurFunctionDecl(); QualType CurFuncResQT = CurFunctionDecl->getResultType(); if (CurFuncResQT.getTypePtr()->isVoidType()) // this function cannot use continuation with the environment. return true; Scope *SavedScope = getCurScope(); DeclContext *SavedContext = Actions.CurContext; TypeSourceInfo *CurFuncTI = Actions.Context.CreateTypeSourceInfo(CurFuncResQT); sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val(); Actions.CurContext = static_cast<DeclContext *>(Actions.Context.getTranslationUnitDecl()); Scope *TopScope = getCurScope(); while(TopScope->getParent() != NULL) TopScope = TopScope->getParent(); Actions.CurScope = TopScope; DeclGroupPtrTy returnDecl = DeclGroupPtrTy(); SourceLocation Loc = Tok.getLocation(); ParsingDeclSpec PDS(*this); setTST(&PDS, DeclSpec::TST___code); ParsingDeclarator D(*this, PDS, static_cast<Declarator::TheContext>(Declarator::FileContext)); D.SetIdentifier(CreateUniqueIdentifierInfo(__CBC_RET_CODE_BASE_NAME, Loc),Loc); ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope|Scope::FunctionDeclarationScope); bool IsAmbiguous = false; bool HasProto = true; SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc; DeclSpec FDS(AttrFactory); bool RefQualifierIsLValueRef = true; ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; ParmVarDecl *Param; IdentifierInfo *retvalII = CreateIdentifierInfo(__CBC_RETVAL_NAME, Loc); Param = CreateParam(retvalII); Param->setTypeSourceInfo(CurFuncTI); Param->setType(CurFuncResQT); ParamInfo.push_back(DeclaratorChunk::ParamInfo(retvalII, Loc, Param, 0)); IdentifierInfo *envII = CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc); Param = CreateParam(envII, 1, DeclSpec::TST_void); ParamInfo.push_back(DeclaratorChunk::ParamInfo(envII, Loc, Param, 0)); D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, IsAmbiguous, Loc, ParamInfo.data(), ParamInfo.size(), EllipsisLoc, Loc, FDS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, SourceLocation(), ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, Loc, Loc, D, TrailingReturnType), FnAttrs, Loc); PrototypeScope.Exit(); Decl *TheDecl; ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Decl *BodyRes = Actions.ActOnStartOfFunctionDef(getCurScope(), D); D.complete(BodyRes); D.getMutableDeclSpec().abort(); Actions.ActOnDefaultCtorInitializers(BodyRes); StmtResult FnBody; StmtVector FnStmts; StmtResult innerR; ExprResult retvalAssginmentExpr,LHS; ExprVector ArgExprs; CommaLocsTy CommaLocs; DeclSpec envDS(AttrFactory); IdentifierInfo *structName = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc); setTST(&envDS, DeclSpec::TST_struct, structName); Declarator envDInfo(envDS, Declarator::TypeNameContext); envDInfo.SetRangeEnd(Loc); DeclSpec starDS(AttrFactory); starDS.Finish(Diags, PP); envDInfo.SetIdentifier(0,Loc); envDInfo.AddTypeInfo(DeclaratorChunk::getPointer(starDS.getTypeQualifiers(), Loc, starDS.getConstSpecLoc(), starDS.getVolatileSpecLoc(), starDS.getRestrictSpecLoc()), starDS.getAttributes(), SourceLocation()); ExprVector ArgExprs2; LHS = LookupNameAndBuildExpr(envII); ArgExprs2.push_back(LHS.release()); LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs2); Expr *envCastExpr = LHS.take(); TypeSourceInfo *castTInfo = Actions.GetTypeForDeclaratorCast(envDInfo, envCastExpr->getType()); LHS = Actions.MaybeConvertParenListExprToParenExpr(getCurScope(), envCastExpr); envCastExpr = LHS.take(); LHS = Actions.BuildCStyleCastExpr(Loc, castTInfo, Loc, envCastExpr); ArgExprs.push_back(LHS.release()); LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs); LHS = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_POINTER_NAME, Loc), LHS.take(), true); Expr *ret_pCastExpr = LHS.take(); DeclarationName noValDeclName; TypeSourceInfo *CurFuncTypesPointerTI = Actions.Context.CreateTypeSourceInfo(Actions.BuildPointerType(CurFuncResQT, Loc, noValDeclName)); LHS = Actions.BuildCStyleCastExpr(Loc, CurFuncTypesPointerTI, Loc, ret_pCastExpr); LHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::star, LHS.get()); ExprResult RHS; RHS = LookupNameAndBuildExpr(retvalII); retvalAssginmentExpr = Actions.ActOnBinOp(getCurScope(), Loc, tok::equal, LHS.take(), RHS.take()); innerR = Actions.ActOnExprStmt(retvalAssginmentExpr); if(innerR.isUsable()) FnStmts.push_back(innerR.release()); ExprResult ljExpr,ljLHS; ljExpr = IIToExpr(CreateIdentifierInfo("longjmp", Loc), tok::l_paren); ExprVector ljArgExprs; DeclSpec ljDS(AttrFactory); setTST(&ljDS, DeclSpec::TST_struct, structName); Declarator ljD(ljDS, Declarator::TypeNameContext); ljD.SetRangeEnd(Loc); DeclSpec starDS2(AttrFactory); starDS2.Finish(Diags, PP); ljD.ExtendWithDeclSpec(starDS2); ljD.SetIdentifier(0, Loc); ljD.AddTypeInfo(DeclaratorChunk::getPointer(ljDS.getTypeQualifiers(), Loc, ljDS.getConstSpecLoc(), ljDS.getVolatileSpecLoc(), ljDS.getRestrictSpecLoc()), ljDS.getAttributes(), SourceLocation()); ljLHS = LookupNameAndBuildExpr(envII); Expr *ljCastExpr = ljLHS.take(); TypeSourceInfo *ljCastTInfo = Actions.GetTypeForDeclaratorCast(ljD, ljCastExpr->getType()); ljLHS = Actions.BuildCStyleCastExpr(Loc, ljCastTInfo, Loc, ljCastExpr); ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.take()); ljLHS = LookupMemberAndBuildExpr(envII, ljLHS.take(), true); ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.take()); ljArgExprs.push_back(ljLHS.release()); CommaLocs.push_back(Loc); ljLHS = Actions.ActOnIntegerConstant(Loc, 1 /* return value for setjmp */); ljArgExprs.push_back(ljLHS.release()); ljExpr = Actions.ActOnCallExpr(getCurScope(), ljExpr.take(), Loc, ljArgExprs, Loc, 0); innerR = Actions.ActOnExprStmt(ljExpr); if(innerR.isUsable()) FnStmts.push_back(innerR.release()); FnBody = Actions.ActOnCompoundStmt(Loc, Loc, FnStmts, false); BodyScope.Exit(); TheDecl = Actions.ActOnFinishFunctionBody(BodyRes, FnBody.take()); returnDecl = Actions.ConvertDeclToDeclGroup(TheDecl); (&Actions.getASTConsumer())->HandleTopLevelDecl(returnDecl.get()); Actions.CurScope = SavedScope; Actions.CurContext = SavedContext; Actions.FunctionScopes.push_back(SavedFSI); return false; } /// IIToExpr - Create ExprResult from IdentifierInfo. /// It is used when II is a not primary expression such as not primary types, a function's name, etc. ExprResult Parser::IIToExpr(IdentifierInfo *II, tok::TokenKind Kind){ SourceLocation Loc = Tok.getLocation(); Token Next,IITok; Next.setKind(Kind); ExternalSpace::StatementFilterCCC CCCValidator(Next); CXXScopeSpec SS; Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, II, Loc, Next, false, &CCCValidator); IITok.startToken(); IITok.setLocation(Loc); IITok.setIdentifierInfo(II); IITok.setKind(tok::annot_primary_expr); setExprAnnotation(IITok, Classification.getExpression()); IITok.setAnnotationEndLoc(Loc); PP.AnnotateCachedTokens(IITok); return getExprAnnotation(IITok); } /// CreateComplexStmtRet - Create return value for complex statements. /// /// ({ /* some statements */ /// return_value; )}; /// ^^^^^^^^^^^^^ Create it. StmtResult Parser::CreateComplexStmtRet(IdentifierInfo *II, bool IsAddressOfOperand){ ExprResult ER; if (IsAddressOfOperand) { ER = LookupNameAndBuildExpr(II, true); ER = Actions.ActOnUnaryOp(getCurScope(), Tok.getLocation(), tok::amp, ER.get()); } else ER = IIToExpr(II,tok::semi); return Actions.ActOnExprStmt(ER); } /// CreateParam - Create paramator for functions. /// /// int funcname(int aua) { /// ^^^^^^^ Create it. ParmVarDecl* Parser::CreateParam(IdentifierInfo *II, int pointerNum, DeclSpec::TST T){ SourceLocation Loc = Tok.getLocation(); DeclSpec DS(AttrFactory); setTST(&DS, T); Declarator ParamDeclarator(DS, Declarator::PrototypeContext); ParamDeclarator.SetIdentifier(II, Loc); for(int i = 0;i<pointerNum; i++){ DeclSpec pointerDS(AttrFactory); pointerDS.Finish(Diags, PP); ParamDeclarator.AddTypeInfo(DeclaratorChunk::getPointer(pointerDS.getTypeQualifiers(), Loc, pointerDS.getConstSpecLoc(), pointerDS.getVolatileSpecLoc(), pointerDS.getRestrictSpecLoc()), pointerDS.getAttributes(),SourceLocation()); } ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Actions.ActOnParamDeclarator(getCurScope(), ParamDeclarator)); return Param; } /// setTST - set TypeSpecifierType(TST) DeclSpec. /// TST is specifiers the kind of type such as int, double, char, etc. void Parser::setTST(DeclSpec *DS, DeclSpec::TST T, IdentifierInfo* Name){ SourceLocation Loc = Tok.getLocation(); bool isInvalid = false; const char *PrevSpec = 0; unsigned DiagID = 0; CXXScopeSpec SS; DS->SetRangeStart(Loc); DS->SetRangeEnd(Loc); if (T == DeclSpec::TST_struct) { ParsedAttributesWithRange attrs(AttrFactory); DeclResult TagOrTempResult = true; bool Owned = false; bool IsDependent = false; MultiTemplateParamsArg TParams; TagOrTempResult = Actions.ActOnTag(getCurScope(), T, Sema::TUK_Reference, Loc, SS, Name, Loc, attrs.getList(), AS_none, DS->getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, clang::TypeResult()); isInvalid = DS->SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, TagOrTempResult.get(), Owned); } else if (T == DeclSpec::TST_typename) { Token Next,TypeTok; Next.setKind(tok::identifier); ExternalSpace::StatementFilterCCC CCCValidator(Next); Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, Loc, Next, false, &CCCValidator); TypeTok.startToken(); TypeTok.setLocation(Loc); TypeTok.setIdentifierInfo(Name); TypeTok.setKind(tok::annot_typename); setTypeAnnotation(TypeTok, Classification.getType()); TypeTok.setAnnotationEndLoc(Loc); PP.AnnotateCachedTokens(TypeTok); if (TypeTok.getAnnotationValue()) { ParsedType PT = getTypeAnnotation(TypeTok); isInvalid = DS->SetTypeSpecType(T, Loc, PrevSpec, DiagID, PT); } else DS->SetTypeSpecError(); } else isInvalid = DS->SetTypeSpecType(T, Loc, PrevSpec, DiagID); DS->Finish(Diags, PP); if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); assert(DiagID); if (DiagID == diag::ext_duplicate_declspec) Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); else Diag(Tok, DiagID) << PrevSpec; } } /// CheckTheSjHeader - Check whether setjmp.h has been already included or not. /// If not, include it. void Parser::CheckTheSjHeader(){ SourceLocation Loc = Tok.getLocation(); LookupResult R(Actions, CreateIdentifierInfo("setjmp", Loc), Loc, Actions.LookupOrdinaryName, Actions.ForRedeclaration); if (!Actions.LookupName(R, getCurScope())){ // look up the setjmp if (PP.IncludeHeader(Tok, "setjmp.h")) ConsumeToken(); } } #endif