view tools/clang/lib/Parse/ParseCbC.cpp @ 56:bdef5c940791

copy the previous function's return type to return value
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Thu, 23 Jan 2014 23:14:57 +0900
parents d48478628b39
children 88b0e1f890d7
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/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/ADT/SmallString.h"
#include "clang/Sema/Lookup.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/AST/ASTConsumer.h"

#include <cmath>
#include <sstream>
#include <string>
#include "CbCHelper.h"

using namespace clang;

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;
};
}

namespace CbCSpace{
  enum AssignmentFlags {
    HasStar   = 0x01,
    HasAmp    = 0x02,
    HasPeriod = 0x04,
    HasArrow  = 0x08
  };
  
  bool hasStar(unsigned F) { return F & HasStar; }
  bool hasAmp(unsigned F) { return F & HasAmp; }
  bool hasPeriod(unsigned F) { return F & HasPeriod; }
  bool hasArrow(unsigned F) { return F & HasArrow; }

  enum DeclarationFlags {
    ArrayType     = 0x01,
    PointerType   = 0x02,
    CbCReturnFunc  = 0x04,
    CopyParentType = 0x08
  };
  
  bool isArray(unsigned F) { return F & ArrayType; }
  bool isPointer(unsigned F) { return F & PointerType; }
  bool isCbCRetFunc(unsigned F) { return F & CbCReturnFunc; }
  bool shouldCopyParentsType(unsigned F) { return F & CopyParentType; }
}


bool Parser::PrepareForGotoWithTheEnv(){
  StmtResult Res;
  SourceLocation Loc = Tok.getLocation();

  IdentifierInfo *bufII, *retvalII, *structII, *__CbC_envII, *__CbC_retII,*envII, *ret_pII, *retcsII;
  bufII = CreateUniqueIdentifierInfo(__CBC_BUF_NAME, Loc);
  retvalII = CreateUniqueIdentifierInfo(__CBC_RETVAL_NAME, Loc);
  structII = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc);
  __CbC_envII = CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc);
  __CbC_retII = CreateIdentifierInfo(__CBC_RETURN_NAME, Loc);
  envII = CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc);
  ret_pII = CreateIdentifierInfo(__CBC_STRUCT_POINTER_NAME, Loc);
  retcsII = CreateUniqueIdentifierInfo(__CBC_RET_CODE_BASE_NAME, Loc);

  if (CreateRetFunction()) { // error check : function type is void or not.
    Diag(Tok, diag::err_cannot_use_goto_with_env);
    return true;
  }
    
  Res = CreateDeclStmt(__CbC_retII, CbCSpace::CbCReturnFunc, DeclSpec::TST___code);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateDeclStmt(__CbC_envII, 0, DeclSpec::TST_struct, structII);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateDeclStmt(bufII, 0, DeclSpec::TST_typename, CreateIdentifierInfo("jmp_buf", Loc));
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateDeclStmt(retvalII, CbCSpace::CopyParentType);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateAssignmentStmt(__CbC_envII, retvalII, CbCSpace::HasPeriod, CbCSpace::HasAmp, ret_pII);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateAssignmentStmt(__CbC_envII, bufII, CbCSpace::HasPeriod, 0, envII);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());

  Res = CreateSjForContinuationWithEnv();
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());
      
  Res = CreateAssignmentStmt(__CbC_retII, retcsII);
  if (Res.isUsable())
    Stmtsp->push_back(Res.release());
  return false;
}


StmtResult Parser::CreateAssignmentStmt(IdentifierInfo* LHSII,IdentifierInfo* RHSII,unsigned LHSFlags,unsigned RHSFlags,
					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 ( CbCSpace::hasPeriod(LHSFlags) ) 
    LHS = LookupMemberAndBuildExpr(extraLHSII, LHS.take(), false);
  else if ( CbCSpace::hasArrow(LHSFlags) ) 
    LHS = LookupMemberAndBuildExpr(extraLHSII, LHS.take(), true); // It is not sure.
  
  RHS = LookupAndDeclareName(RHSII);
  if ( CbCSpace::hasAmp(RHSFlags) )
    RHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::amp, RHS.get());

  else if ( CbCSpace::hasStar(RHSFlags) )
    RHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::star, RHS.get()); // It is not sure.

  Expr = Actions.ActOnBinOp(getCurScope(), Loc,tok::equal,LHS.take(),RHS.take());
  
  return Actions.ActOnExprStmt(Expr);
}

StmtResult Parser::CreateDeclStmt(IdentifierInfo *II, unsigned DeclFlags, DeclSpec::TST valueType, IdentifierInfo* Name, const char* size){
  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 (CbCSpace::isCbCRetFunc(DeclFlags)) {
    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;
  }
  if (CbCSpace::isArray(DeclFlags))
    CreateArrayDecl(D, Loc, size);
  
  SmallVector<Decl *, 8> DeclsInGroup;
  Decl *FirstDecl;
  
  if (CbCSpace::shouldCopyParentsType(DeclFlags))
    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);
}

/*
 * 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();
  TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R);
  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;
}

void Parser::CreateArrayDecl(ParsingDeclarator &D, SourceLocation Loc, const char* size){
  ExprResult ExprRes;
  ParsedAttributesWithRange attrs(AttrFactory);
  SmallString<128> SpellingBuffer;
  SpellingBuffer.resize(strlen(size) + 1);
  StringRef TokSpelling = StringRef(size, strlen(size));
  NumericLiteralParser Literal(TokSpelling, Loc, PP);
  Expr *sizeRes;
  QualType Ty;
  unsigned MaxWidth = Actions.Context.getTargetInfo().getIntMaxTWidth();
  llvm::APInt ResultVal(MaxWidth, 0);
  Literal.GetIntegerValue(ResultVal);
  unsigned Width = 0;
  unsigned IntSize = Actions.Context.getTargetInfo().getIntWidth();
  Ty = Actions.Context.IntTy;
  Width = IntSize;
  ResultVal = ResultVal.trunc(Width);
  sizeRes = IntegerLiteral::Create(Actions.Context, ResultVal, Ty, Loc);
  ExprRes = Actions.Owned(sizeRes);
  D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false,ExprRes.release(),Loc,Loc),attrs,Loc);
}

StmtResult Parser::CreateSjForContinuationWithEnv(){
  SourceLocation Loc = Tok.getLocation();
  StmtResult IfRes;
  ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, true/* C99 or CXX */);
  ExprResult CondExp;
  Decl *CondVar = 0;

  CondExp = LookupAndDeclareName(CreateIdentifierInfo("setjmp", Loc));
  ExprVector ArgExprs;
  ExprResult __envExprRes = CondExp.get();

  __envExprRes = LookupAndDeclareName(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 = LookupAndDeclareName(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;
}

ExprResult Parser::LookupAndDeclareName(IdentifierInfo *II){
  SourceLocation Loc = Tok.getLocation();
  UnqualifiedId Name;
  CXXScopeSpec SS;
  SourceLocation TemplateKWLoc;
  ExternalSpace::CastExpressionIdValidator Validator(false,true);
  bool IsAddressOfOperand = false;
  Name.setIdentifier(II, Loc);
  return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, false, IsAddressOfOperand, &Validator);
}

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.
void Parser::Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS) {
  ParsingDeclSpec SDS(*this);
  if (SDS.getSourceRange().isInvalid()) {
    SDS.SetRangeStart(Loc);
    SDS.SetRangeEnd(Loc);
  }
  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;
  

  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);
}

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;
}

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;
}

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;
}

bool Parser::CreateRetFunction(){
  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();
  Create__CbC_envStruct(Loc, AS_none);
  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 = LookupAndDeclareName(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 = LookupAndDeclareName(retvalII);
			    
  retvalAssginmentExpr = Actions.ActOnBinOp(getCurScope(), Loc, tok::equal, LHS.take(), RHS.take());
  innerR = Actions.ActOnExprStmt(retvalAssginmentExpr);
  if(innerR.isUsable())
    FnStmts.push_back(innerR.release());

  Token Next,ljTok;
  Next.setKind(tok::l_paren);
  ExternalSpace::StatementFilterCCC CCCValidator(Next);
  CXXScopeSpec SS;
  IdentifierInfo *ljName = CreateIdentifierInfo("longjmp", Loc);
  Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, ljName, Loc, Next, false, &CCCValidator);
  ljTok.startToken();
  ljTok.setLocation(Loc);
  ljTok.setIdentifierInfo(ljName);
  ljTok.setKind(tok::annot_primary_expr);
  setExprAnnotation(ljTok, Classification.getExpression());
  ljTok.setAnnotationEndLoc(Loc);
  PP.AnnotateCachedTokens(ljTok);
  ExprResult ljExpr,ljLHS;
  ljExpr = getExprAnnotation(ljTok);
  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 = LookupAndDeclareName(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;
}

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;

}

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;
  }
}

void Parser::IncludeHeader(const char* HeaderName){
  SourceLocation Loc = Tok.getLocation();
  LookupResult R(Actions, CreateIdentifierInfo("setjmp", Loc), Loc, Actions.LookupOrdinaryName, Actions.ForRedeclaration);
  if (!Actions.LookupName(R, getCurScope())){
    PP.LexHeader(Tok, HeaderName);
    ConsumeToken();
  }
}
#endif