# HG changeset patch # User anatofuz # Date 1583918956 -32400 # Node ID e8a9b4f4d7556d42c136c073b7a53414925a91ed # Parent dbda48fb9435736fdf768dd7acf222d9fd3cb20a pull from 146 diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/AST/ASTContext.h Wed Mar 11 18:29:16 2020 +0900 @@ -946,6 +946,9 @@ // Builtin Types. CanQualType VoidTy; +#ifndef noCbC + CanQualType __CodeTy; +#endif CanQualType BoolTy; CanQualType CharTy; CanQualType WCharTy; // [C++ 3.9.1p5]. diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/AST/CanonicalType.h --- a/clang/include/clang/AST/CanonicalType.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/AST/CanonicalType.h Wed Mar 11 18:29:16 2020 +0900 @@ -280,6 +280,9 @@ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) +#ifndef noCbC + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, is__CodeType) +#endif LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/AST/Type.h Wed Mar 11 18:29:16 2020 +0900 @@ -2006,6 +2006,10 @@ bool isFundamentalType() const; bool isCompoundType() const; +#ifndef noCbC + bool is__CodeType() const; // for CbC +#endif + // Type Predicates: Check to see if this type is structurally the specified // type, ignoring typedefs and qualifiers. bool isFunctionType() const; @@ -6776,10 +6780,22 @@ inline bool Type::isVoidType() const { if (const auto *BT = dyn_cast(CanonicalType)) +#ifndef noCbC + return (BT->getKind() == BuiltinType::Void || BT->getKind() == BuiltinType::__Code); +#else return BT->getKind() == BuiltinType::Void; +#endif return false; } +#ifndef noCbC +inline bool Type::is__CodeType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) + return BT->getKind() == BuiltinType::__Code; + return false; +} +#endif + inline bool Type::isHalfType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() == BuiltinType::Half; @@ -6865,8 +6881,14 @@ inline bool Type::isScalarType() const { if (const auto *BT = dyn_cast(CanonicalType)) +#ifndef noCbC + return BT->getKind() > BuiltinType::Void && + BT->getKind() <= BuiltinType::NullPtr && + BT->getKind() != BuiltinType::__Code; +#else return BT->getKind() > BuiltinType::Void && BT->getKind() <= BuiltinType::NullPtr; +#endif if (const EnumType *ET = dyn_cast(CanonicalType)) // Enums are scalar types, but only if they are defined. Incomplete enums // are not treated as scalar types. diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Basic/Specifiers.h --- a/clang/include/clang/Basic/Specifiers.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Basic/Specifiers.h Wed Mar 11 18:29:16 2020 +0900 @@ -93,6 +93,9 @@ TST_auto_type, // __auto_type extension TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic +#ifndef noCbC + TST___code, +#endif #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types #include "clang/Basic/OpenCLImageTypes.def" TST_error // erroneous type diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Lex/Lexer.h --- a/clang/include/clang/Lex/Lexer.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Lex/Lexer.h Wed Mar 11 18:29:16 2020 +0900 @@ -176,7 +176,11 @@ private: /// Lex - Return the next token in the file. If this is the end of file, it /// return the tok::eof token. This implicitly involves the preprocessor. +#ifndef noCbC + bool Lex(Token &Result, bool ProtoParsing = false); +#else bool Lex(Token &Result); +#endif public: /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma. @@ -565,7 +569,11 @@ /// LexTokenInternal - Internal interface to lex a preprocessing token. Called /// by Lex. /// +#ifndef noCbC + bool LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine, bool ignoreInclude = false); +#else bool LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine); +#endif bool CheckUnicodeWhitespace(Token &Result, uint32_t C, const char *CurPtr); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Lex/Preprocessor.h --- a/clang/include/clang/Lex/Preprocessor.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Lex/Preprocessor.h Wed Mar 11 18:29:16 2020 +0900 @@ -2356,6 +2356,16 @@ /// warnings. void markMacroAsUsed(MacroInfo *MI); +#ifndef noCbC + bool IncludeHeader(Token Tok, const char* Name); + unsigned int SavedDepth; + Token SavedToken; + bool SavedTokenFlag; + void ClearCache(); + void RestoreTokens(Token *Toks, unsigned NumToks); + bool ProtoParsing = false; +#endif + private: Optional getSkippedRangeForExcludedConditionalBlock(SourceLocation HashLoc); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Parse/Parser.h Wed Mar 11 18:29:16 2020 +0900 @@ -1995,6 +1995,13 @@ /// A SmallVector of types. typedef SmallVector TypeVector; +#ifndef noCbC // for CbC + StmtVector* Stmtsp; + const char* curFuncName; + unsigned int UniqueId; + bool ProtoParsing = false; +#endif + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr, ParsedStmtContext StmtCtx = ParsedStmtContext::SubStmt); @@ -2029,6 +2036,9 @@ StmtResult ParseDoStatement(); StmtResult ParseForStatement(SourceLocation *TrailingElseLoc); StmtResult ParseGotoStatement(); +#ifndef noCbC + StmtResult ParseCbCGotoStatement(ParsedAttributesWithRange &Attrs,StmtVector &Stmts); +#endif StmtResult ParseContinueStatement(); StmtResult ParseBreakStatement(); StmtResult ParseReturnStatement(); @@ -2244,6 +2254,32 @@ void ParseStructDeclaration( ParsingDeclSpec &DS, llvm::function_ref FieldsCallback); +#ifndef noCbC + void CreateRetCS(IdentifierInfo* csName); + void Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS); + IdentifierInfo* CreateIdentifierInfo(const char* Name, SourceLocation Loc); + Decl* Create__CbC_envBody(Decl* TagDecl, DeclSpec::TST T, SourceLocation Loc, const char* Name); + ExprResult LookupNameAndBuildExpr(IdentifierInfo *II = 0, bool IsAddressOfOperand = false); + ExprResult LookupMemberAndBuildExpr(IdentifierInfo *II, Expr* Base, bool IsArrow); + StmtResult CreateSjForContinuationWithTheEnv(); + StmtResult CreateAssignmentStmt(IdentifierInfo* LHSII = 0, IdentifierInfo* RHSII = 0, bool LHSisMemberAccess = false, + bool RHShasAmp = false, IdentifierInfo* extraLHSII = 0, IdentifierInfo* extraRHSII = 0); + StmtResult CreateDeclStmt(IdentifierInfo *II = 0, bool isRetCS = false, bool copyType = false, DeclSpec::TST valueType = DeclSpec::TST_int, IdentifierInfo* Name = 0, DeclSpec::TQ TQ = DeclSpec::TQ_unspecified); + IdentifierInfo* CreateUniqueIdentifierInfo(const char* Name, SourceLocation Loc); + ParmVarDecl* CreateParam(IdentifierInfo *II = 0, int pointerNum = 0, DeclSpec::TST T = DeclSpec::TST_int); + Decl* HandleDeclAndChangeDeclType(Declarator &D); + void setTST(DeclSpec *DS = 0, DeclSpec::TST T = DeclSpec::TST_int, IdentifierInfo *Name = 0, DeclSpec::TQ TQ = DeclSpec::TQ_unspecified); + void CheckTheSjHeader(); + ExprResult IIToExpr(IdentifierInfo *II, tok::TokenKind Kind); + StmtResult CreateComplexStmtRet(IdentifierInfo *II, bool IsAddressOfOperand); + ExprResult Prepare__retForGotoWithTheEnvExpr(); + ExprResult Prepare__envForGotoWithTheEnvExpr(); + bool isVoidFunction(); + bool SearchCodeSegmentDeclaration(std::string Name); + void CreatePrototypeDeclaration(); + bool SkipAnyUntil(tok::TokenKind T, SkipUntilFlags Flags = static_cast(0)); + bool NeedPrototypeDeclaration(Token IITok); +#endif bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Sema/DeclSpec.h --- a/clang/include/clang/Sema/DeclSpec.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Sema/DeclSpec.h Wed Mar 11 18:29:16 2020 +0900 @@ -309,6 +309,10 @@ #include "clang/Basic/OpenCLImageTypes.def" static const TST TST_error = clang::TST_error; +#ifndef noCbC + static const TST TST___code = clang::TST___code; +#endif + // type-qualifiers enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ. TQ_unspecified = 0, diff -r dbda48fb9435 -r e8a9b4f4d755 clang/include/clang/Serialization/ASTBitCodes.h --- a/clang/include/clang/Serialization/ASTBitCodes.h Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/include/clang/Serialization/ASTBitCodes.h Wed Mar 11 18:29:16 2020 +0900 @@ -1013,6 +1013,11 @@ /// \brief The '_Sat unsigned long _Fract' type PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69, +#ifndef noCbC + /// \brief The __code type. + PREDEF_TYPE___CODE_ID = 70, +#endif + /// OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/ASTContext.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1240,6 +1240,11 @@ // C99 6.2.5p19. InitBuiltinType(VoidTy, BuiltinType::Void); +#ifndef noCbC + // CbC + InitBuiltinType(__CodeTy, BuiltinType::__Code); +#endif + // C99 6.2.5p2. InitBuiltinType(BoolTy, BuiltinType::Bool); // C99 6.2.5p3. @@ -1895,6 +1900,9 @@ default: llvm_unreachable("Unknown builtin type!"); case BuiltinType::Void: // GCC extension: alignof(void) = 8 bits. +#ifndef noCbC + case BuiltinType::__Code: +#endif Width = 0; Align = 8; break; @@ -6720,6 +6728,9 @@ BuiltinType::Kind kind = BT->getKind(); switch (kind) { case BuiltinType::Void: return 'v'; +#ifndef noCbC + case BuiltinType::__Code: return 'v'; +#endif case BuiltinType::Bool: return 'B'; case BuiltinType::Char8: case BuiltinType::Char_U: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/FormatString.cpp --- a/clang/lib/AST/FormatString.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/FormatString.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -424,6 +424,9 @@ case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: +#ifndef noCbC + case BuiltinType::__Code: +#endif return Match; default: break; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/ItaniumMangle.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -2558,6 +2558,9 @@ std::string type_name; switch (T->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif Out << 'v'; break; case BuiltinType::Bool: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/MicrosoftMangle.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1985,6 +1985,9 @@ // ::= _Z # __float80 (Digital Mars) switch (T->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif Out << 'X'; break; case BuiltinType::SChar: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/NSAPI.cpp --- a/clang/lib/AST/NSAPI.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/NSAPI.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -422,6 +422,9 @@ return NSAPI::NSNumberWithBool; case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::Char8: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/Type.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -2762,6 +2762,10 @@ switch (getKind()) { case Void: return "void"; +#ifndef noCbC + case __Code: + return "__code"; +#endif case Bool: return Policy.Bool ? "bool" : "_Bool"; case Char_S: @@ -3901,6 +3905,9 @@ return ResultIfUnknown; case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/AST/TypeLoc.cpp --- a/clang/lib/AST/TypeLoc.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/AST/TypeLoc.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -319,6 +319,10 @@ switch (getTypePtr()->getKind()) { case BuiltinType::Void: return TST_void; +#ifndef noCbC + case BuiltinType::__Code: + return TST___code; +#endif case BuiltinType::Bool: return TST_bool; case BuiltinType::Char_U: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/BackendUtil.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -496,6 +496,10 @@ Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose; Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments; Options.MCOptions.ABIName = TargetOpts.ABI; +#ifndef noCbC + Options.HasCodeSegment = LangOpts.HasCodeSegment; + Options.GuaranteedTailCallOpt = LangOpts.HasCodeSegment; +#endif for (const auto &Entry : HSOpts.UserEntries) if (!Entry.IsFramework && (Entry.Group == frontend::IncludeDirGroup::Quoted || diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/CGCall.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -756,6 +756,13 @@ unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); +#ifndef noCbC + // if the function is a code segment , set fastcall calling convention. + if(resultType.getTypePtr()->is__CodeType()){ + CC = llvm::CallingConv::Fast; + } +#endif + // Construct the function info. We co-allocate the ArgInfos. FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, paramInfos, resultType, argTypes, required); @@ -1584,7 +1591,14 @@ case ABIArgInfo::Indirect: case ABIArgInfo::Ignore: +#ifndef noCbC + if (FI.getReturnType().getTypePtr()->is__CodeType()) + resultType = llvm::Type::get__CodeTy(getLLVMContext()); + else + resultType = llvm::Type::getVoidTy(getLLVMContext()); +#else resultType = llvm::Type::getVoidTy(getLLVMContext()); +#endif break; case ABIArgInfo::CoerceAndExpand: @@ -1740,6 +1754,11 @@ FpKind = "all"; break; } +#ifndef noCbC + if (getLangOpts().hasCodeSegment()) { + FpKind = "none"; + } +#endif FuncAttrs.addAttribute("frame-pointer", FpKind); FuncAttrs.addAttribute("less-precise-fpmad", @@ -4416,6 +4435,12 @@ IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; } +#ifndef noCbC +/* + terminates local variable pointer life time here. + cf. CodeGenFunction::PopCleanupBlock at clang/lib/CodeGen/CGCleanup.cpp +*/ +#endif // 2. Prepare the function pointer. // If the callee is a bitcast of a non-variadic function to have a @@ -4620,6 +4645,10 @@ if (llvm::CallInst *Call = dyn_cast(CI)) { if (TargetDecl && TargetDecl->hasAttr()) Call->setTailCallKind(llvm::CallInst::TCK_NoTail); +#ifndef noCbC + if (this->FnRetTy.getTypePtr()->is__CodeType() && CallInfo.getReturnType().getTypePtr()->is__CodeType()) + Call->setTailCallKind(llvm::CallInst::TCK_Tail); +#endif } // Add metadata for calls to MSAllocator functions diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/CGCleanup.cpp --- a/clang/lib/CodeGen/CGCleanup.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/CGCleanup.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -569,6 +569,9 @@ } // Ask the cleanup to emit itself. +#ifndef noCbC + if (!CGF.FnRetTy.getTypePtr()->is__CodeType()) // in __code cleanup is done just before tail call (goto) +#endif Fn->Emit(CGF, flags); assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/CGDebugInfo.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -640,6 +640,9 @@ case BuiltinType::NullPtr: return DBuilder.createNullPtrType(); case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif return nullptr; case BuiltinType::ObjCClass: if (!ClassTy) diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/CodeGenTypes.cpp --- a/clang/lib/CodeGen/CodeGenTypes.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/CodeGenTypes.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -408,6 +408,9 @@ case Type::Builtin: { switch (cast(Ty)->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -2947,6 +2947,9 @@ // Types added here must also be added to EmitFundamentalRTTIDescriptors. switch (Ty->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif case BuiltinType::NullPtr: case BuiltinType::Bool: case BuiltinType::WChar_S: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/CodeGen/TargetInfo.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -2619,7 +2619,11 @@ if (const BuiltinType *BT = Ty->getAs()) { BuiltinType::Kind k = BT->getKind(); +#ifndef noCbC + if (k == BuiltinType::Void || k == BuiltinType::__Code) { +#else if (k == BuiltinType::Void) { +#endif Current = NoClass; } else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) { Lo = Integer; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Driver/Types.cpp --- a/clang/lib/Driver/Types.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Driver/Types.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -285,6 +285,9 @@ .Case("c++m", TY_CXXModule) .Case("cppm", TY_CXXModule) .Case("cxxm", TY_CXXModule) +#ifndef noCbC + .Case("cbc", TY_C) +#endif .Default(TY_INVALID); } diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Frontend/CompilerInvocation.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -2024,6 +2024,9 @@ .Case("objective-c", Language::ObjC) .Case("objective-c++", Language::ObjCXX) .Case("renderscript", Language::RenderScript) +#ifndef noCbC + .Case("cbc", Language::C) +#endif .Default(Language::Unknown); // "objc[++]-cpp-output" is an acceptable synonym for diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Frontend/FrontendOptions.cpp --- a/clang/lib/Frontend/FrontendOptions.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Frontend/FrontendOptions.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -31,5 +31,8 @@ .Case("cl", Language::OpenCL) .Case("cu", Language::CUDA) .Cases("ll", "bc", Language::LLVM_IR) +#ifndef noCbC + .Cases("cbc", Language::C) +#endif .Default(Language::Unknown); } diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Index/USRGeneration.cpp --- a/clang/lib/Index/USRGeneration.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Index/USRGeneration.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -658,6 +658,9 @@ unsigned char c = '\0'; switch (BT->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif c = 'v'; break; case BuiltinType::Bool: c = 'b'; break; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Lex/Lexer.cpp --- a/clang/lib/Lex/Lexer.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Lex/Lexer.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -49,6 +49,10 @@ using namespace clang; +#ifndef noCbC +#include +#endif + //===----------------------------------------------------------------------===// // Token Class Implementation //===----------------------------------------------------------------------===// @@ -3136,7 +3140,11 @@ // Note that this doesn't affect IsAtPhysicalStartOfLine. } +#ifndef noCbC +bool Lexer::Lex(Token &Result, bool ProtoParsing) { +#else bool Lexer::Lex(Token &Result) { +#endif // Start a new token. Result.startToken(); @@ -3160,7 +3168,11 @@ IsAtPhysicalStartOfLine = false; bool isRawLex = isLexingRawMode(); (void) isRawLex; +#ifndef noCbC + bool returnedToken = LexTokenInternal(Result, atPhysicalStartOfLine, ProtoParsing); +#else bool returnedToken = LexTokenInternal(Result, atPhysicalStartOfLine); +#endif // (After the LexTokenInternal call, the lexer might be destroyed.) assert((returnedToken || !isRawLex) && "Raw lex must succeed"); return returnedToken; @@ -3171,7 +3183,11 @@ /// has a null character at the end of the file. This returns a preprocessing /// token, not a normal token, as such, it is an internal interface. It assumes /// that the Flags of result have been cleared before calling this. +#ifndef noCbC +bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine, bool ignoreInclude) { +#else bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { +#endif LexNextToken: // New token, can't need cleaning yet. Result.clearFlag(Token::NeedsCleaning); @@ -3833,6 +3849,12 @@ Kind = tok::comma; break; case '#': +#ifndef noCbC + if (ignoreInclude && strncmp(CurPtr, "include", 7) == 0){ + SkipLineComment(Result, CurPtr, TokAtPhysicalStartOfLine); + return true; + } +#endif Char = getCharAndSize(CurPtr, SizeTmp); if (Char == '#') { Kind = tok::hashhash; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Lex/PPDirectives.cpp --- a/clang/lib/Lex/PPDirectives.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Lex/PPDirectives.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -48,6 +48,9 @@ #include #include #include +#ifndef noCbC +#include +#endif using namespace clang; @@ -3094,3 +3097,59 @@ HashToken.getLocation(), CI.IfLoc, /*Foundnonskip*/ true, /*FoundElse*/ CI.FoundElse, ElifToken.getLocation()); } + +#ifndef noCbC +/// IncludeHeader - Include a header file. +/// Current Token is saved for returning current file because it has been already lexed from buffer of input file. +/// When the lexer has already entered a header file, this function return false. +bool Preprocessor::IncludeHeader(Token Tok, const char* Name) { + if (SavedTokenFlag) // If the lexer has already entered a header file, we have to leave this function. + return false; + SourceLocation Loc = Tok.getLocation(); + SavedToken = Tok; + SavedDepth = IncludeMacroStack.size(); + SavedTokenFlag = true; + + CurLexer->ParsingPreprocessorDirective = true; + if (CurLexer) CurLexer->SetKeepWhitespaceMode(false); + CurLexer->MIOpt.resetImmediatelyAfterTopLevelIfndef(); + ++NumDirectives; // number of preprocessor directives. + const int Len = strlen(Name); + const DirectoryLookup *LookupFrom = 0; + Token FilenameTok; + FilenameTok.setKind(tok::angle_string_literal); + FilenameTok.setLocation(Loc); + FilenameTok.setLength(Len); + FilenameTok.setLiteralData(Name); + StringRef Filename; + Filename = StringRef(Name, Len); + bool isAngled = true; // '<' header name '>' + const DirectoryLookup *CurDir; + bool IsMapped = false; + ModuleMap::KnownHeader SuggestedModule; + const FileEntry *File = LookupFile(Loc, Filename, isAngled, LookupFrom, nullptr, CurDir, nullptr, nullptr, + &SuggestedModule, &IsMapped); + if (File == 0) { + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; // setjmp.h was not found + } + SrcMgr::CharacteristicKind FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), SourceMgr.getFileCharacteristic(Loc)); + + if (!HeaderInfo.ShouldEnterIncludeFile(*this, File, false, false, SuggestedModule.getModule())) { + return false; + } + + FileID FID = SourceMgr.createFileID(File, Loc, FileCharacter); + EnterSourceFile(FID, CurDir, FilenameTok.getLocation()); + return true; +} + +void Preprocessor::ClearCache(){ + CachedTokens.clear(); + CachedLexPos = 0; +} + +void Preprocessor::RestoreTokens(Token *Toks, unsigned NumToks){ + EnterCachingLexMode(); + CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Toks, Toks + NumToks); +} +#endif diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Lex/PPLexerChange.cpp --- a/clang/lib/Lex/PPLexerChange.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Lex/PPLexerChange.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -469,6 +469,25 @@ PPCallbacks::ExitFile, FileType, ExitedFID); } +#ifndef noCbC + if (SavedTokenFlag && IncludeMacroStack.size() == SavedDepth){ + Result = SavedToken; + SavedTokenFlag = false; + if (CurLexer->ParsingPreprocessorDirective) { + // Done parsing the "line". + CurLexer->ParsingPreprocessorDirective = false; + + // Restore comment saving mode, in case it was disabled for directive. + CurLexer->resetExtendedTokenMode(); + + // Since we consumed a newline, we are back at the start of a line. + CurLexer->IsAtStartOfLine = true; + CurLexer->IsAtPhysicalStartOfLine = true; + } + return true; + } +#endif + // Restore conditional stack from the preamble right after exiting from the // predefines file. if (ExitedFromPredefinesFile) diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Lex/Preprocessor.cpp --- a/clang/lib/Lex/Preprocessor.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Lex/Preprocessor.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -150,6 +150,7 @@ Ident_AbnormalTermination = nullptr; } + // If using a PCH where a #pragma hdrstop is expected, start skipping tokens. if (usingPCHWithPragmaHdrStop()) SkippingUntilPragmaHdrStop = true; @@ -159,6 +160,11 @@ !this->PPOpts->ImplicitPCHInclude.empty()) SkippingUntilPCHThroughHeader = true; + #ifndef noCbC + SavedDepth = 0; + SavedTokenFlag = false; +#endif + if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); @@ -893,7 +899,11 @@ do { switch (CurLexerKind) { case CLK_Lexer: +#ifndef noCbC + ReturnedToken = CurLexer->Lex(Result, ProtoParsing); +#else ReturnedToken = CurLexer->Lex(Result); +#endif break; case CLK_TokenLexer: ReturnedToken = CurTokenLexer->Lex(Result); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/CbCHelper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/lib/Parse/CbCHelper.h Wed Mar 11 18:29:16 2020 +0900 @@ -0,0 +1,13 @@ +#ifndef _CBC_HELPER_IS_INCLUDED +#define _CBC_HELPER_IS_INCLUDED + +#define __CBC_ENVIRONMENT_NAME "__CbC_environment" +#define __CBC_RETURN_NAME "__CbC_return" +#define __CBC_BUF_NAME "env_buf" +#define __CBC_RETVAL_NAME "retval" +#define __CBC_STRUCT_NAME "__CbC_env" +#define __CBC_STRUCT_ENV_NAME "env" +#define __CBC_STRUCT_POINTER_NAME "ret_p" +#define __CBC_RET_CODE_BASE_NAME "ret" + +#endif diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/ParseCbC.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/lib/Parse/ParseCbC.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -0,0 +1,1059 @@ +#ifndef noCbC + +#include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.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 "clang/Sema/SemaDiagnostic.h" + +#include +#include +#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(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()) + return !candidate.getCorrectionSpecifier() || isa(FD); + if (NextToken.is(tok::equal)) + return candidate.getCorrectionDeclAs(); + if (NextToken.is(tok::period) && + candidate.getCorrectionDeclAs()) + 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_env *)(env))->ret_p = retval; +/// longjmp((int*)(((struct __CbC_env *)env)->env),1); +/// } +ExprResult Parser::Prepare__retForGotoWithTheEnvExpr(){ + + if (isVoidFunction()) { // error check : function type is void or not. + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "continuation with the environment cannot use in the void function"); + Diag(Tok, DiagID); + return ExprError(); + } + + 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 + CreateRetCS(retcsII); + + // __code (*__CbC_return)(); + innerRes = CreateDeclStmt(__CbC_retII, true, false, DeclSpec::TST___code); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // __CbC_return = ret; + innerRes = CreateAssignmentStmt(__CbC_retII, retcsII); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // __CbC_return; + innerRes = CreateComplexStmtRet(__CbC_retII, false); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); + ConsumeToken(); // eat the '__return'. + return Actions.ActOnStmtExpr(Loc, CompoundStmtRes.get(), 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: +/// ({ +/// volatile 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(){ + + if (isVoidFunction()) { // error check : function type is void or not. + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "continuation with the environment cannot use in the void function"); + Diag(Tok, DiagID); + return ExprError(); + } + + StmtResult innerRes; + SourceLocation Loc = Tok.getLocation(); + IdentifierInfo *bufII = CreateIdentifierInfo(__CBC_BUF_NAME, Loc); + IdentifierInfo *retvalII = CreateIdentifierInfo(__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; + ExprResult Result(true); + + // struct __CbC_env __CbC_environment; + innerRes = CreateDeclStmt(__CbC_envII, false, false, DeclSpec::TST_struct, structII, DeclSpec::TQ_volatile); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // returnType retval; + innerRes = CreateDeclStmt(retvalII, false, true); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // jmp_buf env_buf; + innerRes = CreateDeclStmt(bufII, false, false, DeclSpec::TST_typename, CreateIdentifierInfo("jmp_buf", Loc)); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // __CbC_environment.ret_p = &retval; + innerRes = CreateAssignmentStmt(__CbC_envII, retvalII, true, true, ret_pII); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // __CbC_environment.env = env_buf; + innerRes = CreateAssignmentStmt(__CbC_envII, bufII, true, false, envII); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // create statements of setjmp + innerRes = CreateSjForContinuationWithTheEnv(); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + // __CbC_environment; + innerRes = CreateComplexStmtRet(__CbC_envII, true); + if (innerRes.isUsable()) + CompoundStmts.push_back(innerRes.get()); + + StmtResult CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); + ConsumeToken(); // eat the '__environment'. + Result = Actions.ActOnStmtExpr(Loc, CompoundStmtRes.get(), Loc); + + // cast + ParsedType CastTy; + DeclSpec void_DS(AttrFactory); + setTST(&void_DS, DeclSpec::TST_void); + Declarator DeclaratorInfo(void_DS, DeclaratorContext::TypeNameContext); + DeclSpec star_DS(AttrFactory); + star_DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); + DeclaratorInfo.ExtendWithDeclSpec(star_DS); + DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); + DeclaratorInfo.AddTypeInfo(DeclaratorChunk::getPointer(star_DS.getTypeQualifiers(), Loc,star_DS.getConstSpecLoc(),star_DS.getVolatileSpecLoc(), + star_DS.getRestrictSpecLoc(),star_DS.getAtomicSpecLoc(),star_DS.getUnalignedSpecLoc()),star_DS.getAttributes(),SourceLocation()); + return Actions.ActOnCastExpr(getCurScope(), Loc, DeclaratorInfo, CastTy,Loc, Result.get()); + +} + +/// 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); + std::unique_ptr Validator(new ExternalSpace::StatementFilterCCC(Next)); + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, LHSII, Loc, Next, false, SS.isEmpty() ? std::move(Validator) : 0); + setExprAnnotation(LHSToken, Classification.getExpression()); + LHSToken.setAnnotationEndLoc(Loc); + PP.AnnotateCachedTokens(LHSToken); + + LHS = getExprAnnotation(LHSToken); + + if (LHSisMemberAccess) + LHS = LookupMemberAndBuildExpr(extraLHSII, LHS.get(), false); + + RHS = LookupNameAndBuildExpr(RHSII); + if (RHShasAmp) + RHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::amp, RHS.get()); + + Expr = Actions.ActOnBinOp(getCurScope(), Loc,tok::equal,LHS.get(),RHS.get()); + + 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, DeclSpec::TQ TQ){ + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + SourceLocation Loc = Tok.getLocation(); + DeclGroupPtrTy DeclGPT; + ParsingDeclSpec DS(*this); + DeclSpec *DSp; + DSp = &DS; + + setTST(&DS, valueType, Name, TQ); + ParsingDeclarator D(*this, DS, static_cast(DeclaratorContext::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(Actions, Policy); + + D.AddTypeInfo(DeclaratorChunk::getPointer(FDS.getTypeQualifiers(), Loc, FDS.getConstSpecLoc(), FDS.getVolatileSpecLoc(), + FDS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), FDS.getUnalignedSpecLoc()), FDS.getAttributes(), SourceLocation()); + D.setGroupingParens(hadGroupingParens); + + + ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope| + (D.isFunctionDeclaratorAFunctionDeclaration() ? Scope::FunctionDeclarationScope : 0)); + bool HasProto = false; + SmallVector ParamInfo; + SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, RestrictQualifierLoc; + DeclSpec FPDS(AttrFactory); + bool RefQualifierIsLValueRef = true; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + SmallVector DynamicExceptions; + SmallVector DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens = 0; + ParsedAttributes FnAttrs(AttrFactory); + TypeResult TrailingReturnType; + + ParmVarDecl *Param; + FunctionDecl *CurFunctionDecl = Actions.getCurFunctionDecl(); + QualType CurFuncResQT = CurFunctionDecl->getReturnType(); + 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, RefQualifierLoc, SourceLocation(), + ESpecType, ESpecRange.getBegin(), + DynamicExceptions.data(), DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, ExceptionSpecTokens, None, Loc, Loc, D, TrailingReturnType), + FnAttrs, Loc); + PrototypeScope.Exit(); + DSp = &FDS; + } + + SmallVector 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()->getReturnType(); // copy a type + TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R); // copy a type infomation + Scope *S = getCurScope(); + LookupResult Previous(Actions, NameInfo, Actions.LookupOrdinaryName, Actions.ForVisibleRedeclaration); + 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; + StmtResult InitStmt; + Sema::ConditionResult Cond; + + CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("__builtin_setjmp", Loc)); + ExprVector ArgExprs; + ExprResult __envExprRes = CondExp.get(); + + __envExprRes = LookupNameAndBuildExpr(CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc)); + __envExprRes = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc), __envExprRes.get(), false); + + ArgExprs.push_back(__envExprRes.get()); + CondExp = Actions.ActOnCallExpr(getCurScope(), CondExp.get(), Loc, ArgExprs, Loc, 0); + Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExp.get(), Sema::ConditionKind::Boolean); + + + 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(CreateIdentifierInfo(__CBC_RETVAL_NAME, Loc)); + innerStmtRes = Actions.ActOnReturnStmt(Loc, innerExprRes.get(), getCurScope()); + if (innerStmtRes.isUsable()) + innerStmts.push_back(innerStmtRes.get()); + StmtRes = Actions.ActOnCompoundStmt(Loc, Loc,innerStmts, false); + StmtResult ThenStmt(StmtRes); + InnerScope.Exit(); + IfScope.Exit(); + StmtResult ElseStmt; + IfRes = Actions.ActOnIfStmt(Loc, false, CondExp.get(), Cond, 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; + std::unique_ptr Validator(new ExternalSpace::CastExpressionIdValidator(false,true)); + Name.setIdentifier(II, Loc); + return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, false, IsAddressOfOperand, std::move(Validator)); +} + +/// LookupMemberAndBuildExpr - 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(); + CXXScopeSpec SS; + UnqualifiedId Name; + SourceLocation TemplateKWLoc; + tok::TokenKind OpKind = (IsArrow ? tok::arrow : tok::period); + Name.setIdentifier(II,Loc); + return Actions.ActOnMemberAccessExpr(getCurScope(), Base, Loc, OpKind, SS, TemplateKWLoc, Name, nullptr); +} + + +/// 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.ForVisibleRedeclaration); + 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(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(), false, false); + + 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 FieldDecls; + + FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME)); + FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_ENV_NAME)); + + Actions.ActOnFields(getCurScope(),Loc, TagDecl, FieldDecls,Loc, Loc,attrs.getList()); + StructScope.Exit(); + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, Loc); + + 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){ + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + 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(Actions, Policy); + DeclaratorInfo.D.SetIdentifier(CreateIdentifierInfo(Name, Loc),Loc); + + DeclaratorInfo.D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,DS.getConstSpecLoc(), + DS.getVolatileSpecLoc(),DS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), + 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(TokenForII.getRawIdentifier()); + 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 : +/// current 'function name' '..' 'variable name' 'uniqueID' +/// 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 << UniqueId; + II = CreateIdentifierInfo(os.str().c_str(), Loc); + UniqueId++; // Modify the unique ID. + 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((void*)(((struct __CbC_environment *)env)->env),1); +/// } +void Parser::CreateRetCS(IdentifierInfo *csName){ + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + QualType CurFuncResQT = Actions.getCurFunctionDecl()->getReturnType(); + + 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(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(DeclaratorContext::FileContext)); + D.SetIdentifier(csName, Loc); + ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope|Scope::FunctionDeclarationScope); + bool IsAmbiguous = false; + bool HasProto = true; + SmallVector ParamInfo; + SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, RestrictQualifierLoc; + DeclSpec FDS(AttrFactory); + bool RefQualifierIsLValueRef = true; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + SmallVector DynamicExceptions; + SmallVector DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens = 0; + 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, RestrictQualifierLoc, SourceLocation(), + ESpecType, ESpecRange.getBegin(), + DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, ExceptionSpecTokens, None, + Loc, Loc, D, TrailingReturnType), FnAttrs, Loc); + PrototypeScope.Exit(); + + Decl *TheDecl; + ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); + Sema::SkipBodyInfo SkipBody; + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(); + Decl *BodyRes = Actions.ActOnStartOfFunctionDef(getCurScope(), D, + TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams : MultiTemplateParamsArg(), + &SkipBody); + + 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, DeclaratorContext::TypeNameContext); + envDInfo.SetRangeEnd(Loc); + DeclSpec starDS(AttrFactory); + starDS.Finish(Actions, Policy); + envDInfo.SetIdentifier(0,Loc); + envDInfo.AddTypeInfo(DeclaratorChunk::getPointer(starDS.getTypeQualifiers(), Loc, + starDS.getConstSpecLoc(), + starDS.getVolatileSpecLoc(), + starDS.getRestrictSpecLoc(), + starDS.getAtomicSpecLoc(), + starDS.getUnalignedSpecLoc()), + starDS.getAttributes(), + SourceLocation()); + ExprVector ArgExprs2; + LHS = LookupNameAndBuildExpr(envII); + ArgExprs2.push_back(LHS.get()); + LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs2); + Expr *envCastExpr = LHS.get(); + TypeSourceInfo *castTInfo = Actions.GetTypeForDeclaratorCast(envDInfo, envCastExpr->getType()); + LHS = Actions.MaybeConvertParenListExprToParenExpr(getCurScope(), envCastExpr); + envCastExpr = LHS.get(); + LHS = Actions.BuildCStyleCastExpr(Loc, castTInfo, Loc, envCastExpr); + ArgExprs.push_back(LHS.get()); + LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs); + LHS = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_POINTER_NAME, Loc), + LHS.get(), true); + Expr *ret_pCastExpr = LHS.get(); + 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.get(), RHS.get()); + innerR = Actions.ActOnExprStmt(retvalAssginmentExpr); + if(innerR.isUsable()) + FnStmts.push_back(innerR.get()); + + ExprResult ljExpr,ljLHS; + ljExpr = IIToExpr(CreateIdentifierInfo("__builtin_longjmp", Loc), tok::l_paren); + ExprVector ljArgExprs; + DeclSpec ljDS(AttrFactory); + setTST(&ljDS, DeclSpec::TST_struct, structName); + + Declarator ljD(ljDS, DeclaratorContext::TypeNameContext); + ljD.SetRangeEnd(Loc); + DeclSpec starDS2(AttrFactory); + starDS2.Finish(Actions, Policy); + ljD.ExtendWithDeclSpec(starDS2); + ljD.SetIdentifier(0, Loc); + ljD.AddTypeInfo(DeclaratorChunk::getPointer(ljDS.getTypeQualifiers(), Loc, + ljDS.getConstSpecLoc(), + ljDS.getVolatileSpecLoc(), + ljDS.getRestrictSpecLoc(), + ljDS.getAtomicSpecLoc(), + ljDS.getUnalignedSpecLoc()), + ljDS.getAttributes(), + SourceLocation()); + ljLHS = LookupNameAndBuildExpr(envII); + Expr *ljCastExpr = ljLHS.get(); + TypeSourceInfo *ljCastTInfo = Actions.GetTypeForDeclaratorCast(ljD, ljCastExpr->getType()); + ljLHS = Actions.BuildCStyleCastExpr(Loc, ljCastTInfo, Loc, ljCastExpr); + ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.get()); + ljLHS = LookupMemberAndBuildExpr(envII, ljLHS.get(), true); + ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.get()); + ljArgExprs.push_back(ljLHS.get()); + CommaLocs.push_back(Loc); + ljLHS = Actions.ActOnIntegerConstant(Loc, 1 /* return value for setjmp */); + ljArgExprs.push_back(ljLHS.get()); + ljExpr = Actions.ActOnCallExpr(getCurScope(), ljExpr.get(), Loc, ljArgExprs, Loc, 0); + innerR = Actions.ActOnExprStmt(ljExpr); + if(innerR.isUsable()) + FnStmts.push_back(innerR.get()); + FnBody = Actions.ActOnCompoundStmt(Loc, Loc, FnStmts, false); + BodyScope.Exit(); + TheDecl = Actions.ActOnFinishFunctionBody(BodyRes, FnBody.get()); + returnDecl = Actions.ConvertDeclToDeclGroup(TheDecl); + (&Actions.getASTConsumer())->HandleTopLevelDecl(returnDecl.get()); + Actions.CurScope = SavedScope; + Actions.CurContext = SavedContext; + Actions.FunctionScopes.push_back(SavedFSI); +} + +/// 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); + std::unique_ptr CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); + CXXScopeSpec SS; + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, II, Loc, Next, false, std::move(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){ + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + SourceLocation Loc = Tok.getLocation(); + DeclSpec DS(AttrFactory); + setTST(&DS, T); + Declarator ParamDeclarator(DS, DeclaratorContext::PrototypeContext); + ParamDeclarator.SetIdentifier(II, Loc); + for(int i = 0;i(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, DeclSpec::TQ TQ){ + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + SourceLocation Loc = Tok.getLocation(); + bool isInvalid = false; + const char *PrevSpec = 0; + unsigned DiagID = 0; + CXXScopeSpec SS; + DS->SetRangeStart(Loc); + DS->SetRangeEnd(Loc); + if (TQ != DeclSpec::TQ_unspecified) { + isInvalid = DS->SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, + getLangOpts()); + } + + 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(), false, false); + isInvalid = DS->SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, TagOrTempResult.get(), Owned, Policy); + } + else if (T == DeclSpec::TST_typename) { + Token Next,TypeTok; + Next.setKind(tok::identifier); + std::unique_ptr CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, Loc, Next, false, std::move(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, Policy); + } else + DS->SetTypeSpecError(); + } + else + isInvalid = DS->SetTypeSpecType(T, Loc, PrevSpec, DiagID, Policy); + + DS->Finish(Actions, Policy); + 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.ForVisibleRedeclaration); + if (!Actions.LookupName(R, getCurScope())){ // look up the setjmp + if (PP.IncludeHeader(Tok, "setjmp.h")) + ConsumeToken(); + } +} + +/// isVoidFunction - Return true if current function return type is void. +bool Parser::isVoidFunction(){ + return Actions.getCurFunctionDecl()->getReturnType().getTypePtr()->isVoidType(); +} + +/// ParseCbCGotoStatement +/// jump-statement: +/// [CbC] 'goto' codeSegment ';' +/// +StmtResult Parser::ParseCbCGotoStatement(ParsedAttributesWithRange &Attrs,StmtVector &Stmts) { + assert(Tok.is(tok::kw_goto) && "Not a goto stmt!"); + ParseScope CompoundScope(this, Scope::DeclScope); + StmtVector CompoundedStmts; + + SourceLocation gotoLoc = ConsumeToken(); // eat the 'goto'. + StmtResult gotoRes; + Token TokAfterGoto = Tok; + Stmtsp = &Stmts; + + gotoRes = ParseStatementOrDeclaration(Stmts, ACK_Any); + + if (gotoRes.get() == NULL) + return StmtError(); + else if (gotoRes.get()->getStmtClass() != Stmt::CallExprClass) { // if it is not function call + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "expected identifier or codesegment call"); + Diag(TokAfterGoto, DiagID); + return StmtError(); + } + + assert((Attrs.empty() || gotoRes.isInvalid() || gotoRes.isUsable()) && + "attributes on empty statement"); + if (!(Attrs.empty() || gotoRes.isInvalid())) + gotoRes = Actions.ProcessStmtAttributes(gotoRes.get(), Attrs.getList(), Attrs.Range); + if (gotoRes.isUsable()) + CompoundedStmts.push_back(gotoRes.get()); + + // add return; after goto codesegment(); + if (Actions.getCurFunctionDecl()->getReturnType().getTypePtr()->is__CodeType()) { + ExprResult retExpr; + StmtResult retRes; + retRes = Actions.ActOnReturnStmt(gotoLoc, retExpr.get(), getCurScope()); + if (retRes.isUsable()) + CompoundedStmts.push_back(retRes.get()); + } + return Actions.ActOnCompoundStmt(gotoLoc, Tok.getLocation(), CompoundedStmts, false); +} + +/// SearchCodeSegmentDeclaration - Read tokens until we get to the specified code segment declaration. +/// If we can't find it , return false; +bool Parser::SearchCodeSegmentDeclaration(std::string Name){ + while(SkipAnyUntil(tok::kw___code, StopBeforeMatch)){ + if(NextToken().is(tok::identifier) && NextToken().getIdentifierInfo()->getName().str() == Name) + return true; + ConsumeToken(); + } + return false; +} + +bool Parser::NeedPrototypeDeclaration(Token IITok){ + LookupResult LR(Actions, IITok.getIdentifierInfo(), IITok.getLocation(), Actions.LookupOrdinaryName); + CXXScopeSpec SS; + Actions.LookupParsedName(LR, getCurScope(), &SS, !(Actions.getCurMethodDecl())); + + return (LR.getResultKind() == LookupResult::NotFound); +} + +/// CreatePrototypeDeclaration - Create prototype declaration by it's definition. +void Parser::CreatePrototypeDeclaration(){ + // move to the top level scope + Scope *SavedScope = getCurScope(); + DeclContext *SavedContext = Actions.CurContext; + sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val(); + Actions.CurContext = static_cast(Actions.Context.getTranslationUnitDecl()); + Scope *TopScope = getCurScope(); + while(TopScope->getParent() != NULL) + TopScope = TopScope->getParent(); + Actions.CurScope = TopScope; + + Token Next = NextToken(); + Token CachedTokens[3] = {Next, PP.LookAhead(1)}; + Token SavedToken = Tok; + Token IITok = Tok.is(tok::identifier) ? Tok : Next; + PP.ClearCache(); + PP.ProtoParsing = true; + ProtoParsing = true; + + const DirectoryLookup *CurDir = nullptr; + FileID FID = PP.getSourceManager().createFileID(PP.getCurrentFileLexer()->getFileEntry(), IITok.getLocation(), SrcMgr::C_User); + PP.EnterSourceFile(FID,CurDir,IITok.getLocation()); + ConsumeToken(); + + if(SearchCodeSegmentDeclaration(IITok.getIdentifierInfo()->getName().str())){ + DeclGroupPtrTy ProtoDecl; + ParseTopLevelDecl(ProtoDecl); + // add declaration to AST. + if(ProtoDecl) + (&Actions.getASTConsumer())->HandleTopLevelDecl(ProtoDecl.get()); + // File Closing + Token T; + PP.HandleEndOfFile(T, false); + + // recover tokens. + Tok = SavedToken; + PP.RestoreTokens(CachedTokens, 2); + + } + else { + // recover tokens. + CachedTokens[2] = Tok; + Tok = SavedToken; + PP.RestoreTokens(CachedTokens, 3); + } + + // move to the previous scope. + Actions.CurScope = SavedScope; + Actions.CurContext = SavedContext; + Actions.FunctionScopes.push_back(SavedFSI); + + ProtoParsing = false; + PP.ProtoParsing = false; +} + +static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) { + return (static_cast(L) & static_cast(R)) != 0; +} + +bool Parser::SkipAnyUntil(tok::TokenKind T, SkipUntilFlags Flags){ + const PreprocessorLexer *L = PP.getCurrentFileLexer(); + while(1){ + if(Tok.is(T)){ + if (HasFlagsSet(Flags, StopBeforeMatch)) { + // Noop, don't consume the token. + } else { + ConsumeAnyToken(); + } + return true; + } + else if(PP.getCurrentFileLexer() != L){ + return false; + } + + ConsumeAnyToken(); + } +} + +#endif diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Parse/ParseDecl.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1,2052 +1,8 @@ -//===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the Declaration portions of the Parser interfaces. -// -//===----------------------------------------------------------------------===// - -#include "clang/Parse/Parser.h" -#include "clang/Parse/RAIIObjectsForParser.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/PrettyDeclStackTrace.h" -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/Attributes.h" -#include "clang/Basic/CharInfo.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Parse/ParseDiagnostic.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/ParsedTemplate.h" -#include "clang/Sema/Scope.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringSwitch.h" - -using namespace clang; - -//===----------------------------------------------------------------------===// -// C99 6.7: Declarations. -//===----------------------------------------------------------------------===// - -/// ParseTypeName -/// type-name: [C99 6.7.6] -/// specifier-qualifier-list abstract-declarator[opt] -/// -/// Called type-id in C++. -TypeResult Parser::ParseTypeName(SourceRange *Range, - DeclaratorContext Context, - AccessSpecifier AS, - Decl **OwnedType, - ParsedAttributes *Attrs) { - DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); - if (DSC == DeclSpecContext::DSC_normal) - DSC = DeclSpecContext::DSC_type_specifier; - - // Parse the common declaration-specifiers piece. - DeclSpec DS(AttrFactory); - if (Attrs) - DS.addAttributes(*Attrs); - ParseSpecifierQualifierList(DS, AS, DSC); - if (OwnedType) - *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; - - // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, Context); - ParseDeclarator(DeclaratorInfo); - if (Range) - *Range = DeclaratorInfo.getSourceRange(); - - if (DeclaratorInfo.isInvalidType()) - return true; - - return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); -} - -/// Normalizes an attribute name by dropping prefixed and suffixed __. -static StringRef normalizeAttrName(StringRef Name) { - if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) - return Name.drop_front(2).drop_back(2); - return Name; -} - -/// isAttributeLateParsed - Return true if the attribute has arguments that -/// require late parsing. -static bool isAttributeLateParsed(const IdentifierInfo &II) { -#define CLANG_ATTR_LATE_PARSED_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_LATE_PARSED_LIST -} - -/// Check if the a start and end source location expand to the same macro. -static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, - SourceLocation EndLoc) { - if (!StartLoc.isMacroID() || !EndLoc.isMacroID()) - return false; - - SourceManager &SM = PP.getSourceManager(); - if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc)) - return false; - - bool AttrStartIsInMacro = - Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts()); - bool AttrEndIsInMacro = - Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts()); - return AttrStartIsInMacro && AttrEndIsInMacro; -} - -/// ParseGNUAttributes - Parse a non-empty attributes list. -/// -/// [GNU] attributes: -/// attribute -/// attributes attribute -/// -/// [GNU] attribute: -/// '__attribute__' '(' '(' attribute-list ')' ')' -/// -/// [GNU] attribute-list: -/// attrib -/// attribute_list ',' attrib -/// -/// [GNU] attrib: -/// empty -/// attrib-name -/// attrib-name '(' identifier ')' -/// attrib-name '(' identifier ',' nonempty-expr-list ')' -/// attrib-name '(' argument-expression-list [C99 6.5.2] ')' -/// -/// [GNU] attrib-name: -/// identifier -/// typespec -/// typequal -/// storageclass -/// -/// Whether an attribute takes an 'identifier' is determined by the -/// attrib-name. GCC's behavior here is not worth imitating: -/// -/// * In C mode, if the attribute argument list starts with an identifier -/// followed by a ',' or an ')', and the identifier doesn't resolve to -/// a type, it is parsed as an identifier. If the attribute actually -/// wanted an expression, it's out of luck (but it turns out that no -/// attributes work that way, because C constant expressions are very -/// limited). -/// * In C++ mode, if the attribute argument list starts with an identifier, -/// and the attribute *wants* an identifier, it is parsed as an identifier. -/// At block scope, any additional tokens between the identifier and the -/// ',' or ')' are ignored, otherwise they produce a parse error. -/// -/// We follow the C++ model, but don't allow junk after the identifier. -void Parser::ParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc, - LateParsedAttrList *LateAttrs, - Declarator *D) { - assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); - - while (Tok.is(tok::kw___attribute)) { - SourceLocation AttrTokLoc = ConsumeToken(); - unsigned OldNumAttrs = attrs.size(); - unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0; - - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "attribute")) { - SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ; - return; - } - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) { - SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ; - return; - } - // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") )) - do { - // Eat preceeding commas to allow __attribute__((,,,foo)) - while (TryConsumeToken(tok::comma)) - ; - - // Expect an identifier or declaration specifier (const, int, etc.) - if (Tok.isAnnotation()) - break; - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - if (!AttrName) - break; - - SourceLocation AttrNameLoc = ConsumeToken(); - - if (Tok.isNot(tok::l_paren)) { - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_GNU); - continue; - } - - // Handle "parameterized" attributes - if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { - ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, - SourceLocation(), ParsedAttr::AS_GNU, D); - continue; - } - - // Handle attributes with arguments that require late parsing. - LateParsedAttribute *LA = - new LateParsedAttribute(this, *AttrName, AttrNameLoc); - LateAttrs->push_back(LA); - - // Attributes in a class are parsed at the end of the class, along - // with other late-parsed declarations. - if (!ClassStack.empty() && !LateAttrs->parseSoon()) - getCurrentClass().LateParsedDeclarations.push_back(LA); - - // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it - // recursively consumes balanced parens. - LA->Toks.push_back(Tok); - ConsumeParen(); - // Consume everything up to and including the matching right parens. - ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true); - - Token Eof; - Eof.startToken(); - Eof.setLocation(Tok.getLocation()); - LA->Toks.push_back(Eof); - } while (Tok.is(tok::comma)); - - if (ExpectAndConsume(tok::r_paren)) - SkipUntil(tok::r_paren, StopAtSemi); - SourceLocation Loc = Tok.getLocation(); - if (ExpectAndConsume(tok::r_paren)) - SkipUntil(tok::r_paren, StopAtSemi); - if (endLoc) - *endLoc = Loc; - - // If this was declared in a macro, attach the macro IdentifierInfo to the - // parsed attribute. - auto &SM = PP.getSourceManager(); - if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) && - FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) { - CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc); - StringRef FoundName = - Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts()); - IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName); - - for (unsigned i = OldNumAttrs; i < attrs.size(); ++i) - attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin()); - - if (LateAttrs) { - for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i) - (*LateAttrs)[i]->MacroII = MacroII; - } - } - } -} - -/// Determine whether the given attribute has an identifier argument. -static bool attributeHasIdentifierArg(const IdentifierInfo &II) { -#define CLANG_ATTR_IDENTIFIER_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_IDENTIFIER_ARG_LIST -} - -/// Determine whether the given attribute has a variadic identifier argument. -static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) { -#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST -} - -/// Determine whether the given attribute treats kw_this as an identifier. -static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) { -#define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST -} - -/// Determine whether the given attribute parses a type argument. -static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { -#define CLANG_ATTR_TYPE_ARG_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_TYPE_ARG_LIST -} - -/// Determine whether the given attribute requires parsing its arguments -/// in an unevaluated context or not. -static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) { -#define CLANG_ATTR_ARG_CONTEXT_LIST - return llvm::StringSwitch(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); -#undef CLANG_ATTR_ARG_CONTEXT_LIST -} - -IdentifierLoc *Parser::ParseIdentifierLoc() { - assert(Tok.is(tok::identifier) && "expected an identifier"); - IdentifierLoc *IL = IdentifierLoc::create(Actions.Context, - Tok.getLocation(), - Tok.getIdentifierInfo()); - ConsumeToken(); - return IL; -} - -void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax) { - BalancedDelimiterTracker Parens(*this, tok::l_paren); - Parens.consumeOpen(); - - TypeResult T; - if (Tok.isNot(tok::r_paren)) - T = ParseTypeName(); - - if (Parens.consumeClose()) - return; - - if (T.isInvalid()) - return; - - if (T.isUsable()) - Attrs.addNewTypeAttr(&AttrName, - SourceRange(AttrNameLoc, Parens.getCloseLocation()), - ScopeName, ScopeLoc, T.get(), Syntax); - else - Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()), - ScopeName, ScopeLoc, nullptr, 0, Syntax); -} - -unsigned Parser::ParseAttributeArgsCommon( - IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { - // Ignore the left paren location for now. - ConsumeParen(); - - bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName); - bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName); - - // Interpret "kw_this" as an identifier if the attributed requests it. - if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) - Tok.setKind(tok::identifier); - - ArgsVector ArgExprs; - if (Tok.is(tok::identifier)) { - // If this attribute wants an 'identifier' argument, make it so. - bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) || - attributeHasVariadicIdentifierArg(*AttrName); - ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); - - // If we don't know how to parse this attribute, but this is the only - // token in this argument, assume it's meant to be an identifier. - if (AttrKind == ParsedAttr::UnknownAttribute || - AttrKind == ParsedAttr::IgnoredAttribute) { - const Token &Next = NextToken(); - IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma); - } - - if (IsIdentifierArg) - ArgExprs.push_back(ParseIdentifierLoc()); - } - - ParsedType TheParsedType; - if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) { - // Eat the comma. - if (!ArgExprs.empty()) - ConsumeToken(); - - // Parse the non-empty comma-separated list of expressions. - do { - // Interpret "kw_this" as an identifier if the attributed requests it. - if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) - Tok.setKind(tok::identifier); - - ExprResult ArgExpr; - if (AttributeIsTypeArgAttr) { - TypeResult T = ParseTypeName(); - if (T.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return 0; - } - if (T.isUsable()) - TheParsedType = T.get(); - break; // FIXME: Multiple type arguments are not implemented. - } else if (Tok.is(tok::identifier) && - attributeHasVariadicIdentifierArg(*AttrName)) { - ArgExprs.push_back(ParseIdentifierLoc()); - } else { - bool Uneval = attributeParsedArgsUnevaluated(*AttrName); - EnterExpressionEvaluationContext Unevaluated( - Actions, - Uneval ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult ArgExpr( - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); - if (ArgExpr.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return 0; - } - ArgExprs.push_back(ArgExpr.get()); - } - // Eat the comma, move to the next argument - } while (TryConsumeToken(tok::comma)); - } - - SourceLocation RParen = Tok.getLocation(); - if (!ExpectAndConsume(tok::r_paren)) { - SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; - - if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) { - Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen), - ScopeName, ScopeLoc, TheParsedType, Syntax); - } else { - Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, - ArgExprs.data(), ArgExprs.size(), Syntax); - } - } - - if (EndLoc) - *EndLoc = RParen; - - return static_cast(ArgExprs.size() + !TheParsedType.get().isNull()); -} - -/// Parse the arguments to a parameterized GNU attribute or -/// a C++11 attribute in "gnu" namespace. -void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax, - Declarator *D) { - - assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - - ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); - - if (AttrKind == ParsedAttr::AT_Availability) { - ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax); - return; - } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) { - ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - return; - } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) { - ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - return; - } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) { - ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - return; - } else if (attributeIsTypeArgAttr(*AttrName)) { - ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax); - return; - } - - // These may refer to the function arguments, but need to be parsed early to - // participate in determining whether it's a redeclaration. - llvm::Optional PrototypeScope; - if (normalizeAttrName(AttrName->getName()) == "enable_if" && - D && D->isFunctionDeclarator()) { - DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo(); - PrototypeScope.emplace(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | - Scope::DeclScope); - for (unsigned i = 0; i != FTI.NumParams; ++i) { - ParmVarDecl *Param = cast(FTI.Params[i].Param); - Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param); - } - } - - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax); -} - -unsigned Parser::ParseClangAttributeArgs( - IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { - assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - - ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); - - switch (AttrKind) { - default: - return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - case ParsedAttr::AT_ExternalSourceSymbol: - ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - break; - case ParsedAttr::AT_Availability: - ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax); - break; - case ParsedAttr::AT_ObjCBridgeRelated: - ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - break; - case ParsedAttr::AT_TypeTagForDatatype: - ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); - break; - } - return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; -} - -bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs) { - // If the attribute isn't known, we will not attempt to parse any - // arguments. - if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, - getTargetInfo(), getLangOpts())) { - // Eat the left paren, then skip to the ending right paren. - ConsumeParen(); - SkipUntil(tok::r_paren); - return false; - } - - SourceLocation OpenParenLoc = Tok.getLocation(); - - if (AttrName->getName() == "property") { - // The property declspec is more complex in that it can take one or two - // assignment expressions as a parameter, but the lhs of the assignment - // must be named get or put. - - BalancedDelimiterTracker T(*this, tok::l_paren); - T.expectAndConsume(diag::err_expected_lparen_after, - AttrName->getNameStart(), tok::r_paren); - - enum AccessorKind { - AK_Invalid = -1, - AK_Put = 0, - AK_Get = 1 // indices into AccessorNames - }; - IdentifierInfo *AccessorNames[] = {nullptr, nullptr}; - bool HasInvalidAccessor = false; - - // Parse the accessor specifications. - while (true) { - // Stop if this doesn't look like an accessor spec. - if (!Tok.is(tok::identifier)) { - // If the user wrote a completely empty list, use a special diagnostic. - if (Tok.is(tok::r_paren) && !HasInvalidAccessor && - AccessorNames[AK_Put] == nullptr && - AccessorNames[AK_Get] == nullptr) { - Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter); - break; - } - - Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor); - break; - } - - AccessorKind Kind; - SourceLocation KindLoc = Tok.getLocation(); - StringRef KindStr = Tok.getIdentifierInfo()->getName(); - if (KindStr == "get") { - Kind = AK_Get; - } else if (KindStr == "put") { - Kind = AK_Put; - - // Recover from the common mistake of using 'set' instead of 'put'. - } else if (KindStr == "set") { - Diag(KindLoc, diag::err_ms_property_has_set_accessor) - << FixItHint::CreateReplacement(KindLoc, "put"); - Kind = AK_Put; - - // Handle the mistake of forgetting the accessor kind by skipping - // this accessor. - } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) { - Diag(KindLoc, diag::err_ms_property_missing_accessor_kind); - ConsumeToken(); - HasInvalidAccessor = true; - goto next_property_accessor; - - // Otherwise, complain about the unknown accessor kind. - } else { - Diag(KindLoc, diag::err_ms_property_unknown_accessor); - HasInvalidAccessor = true; - Kind = AK_Invalid; - - // Try to keep parsing unless it doesn't look like an accessor spec. - if (!NextToken().is(tok::equal)) - break; - } - - // Consume the identifier. - ConsumeToken(); - - // Consume the '='. - if (!TryConsumeToken(tok::equal)) { - Diag(Tok.getLocation(), diag::err_ms_property_expected_equal) - << KindStr; - break; - } - - // Expect the method name. - if (!Tok.is(tok::identifier)) { - Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name); - break; - } - - if (Kind == AK_Invalid) { - // Just drop invalid accessors. - } else if (AccessorNames[Kind] != nullptr) { - // Complain about the repeated accessor, ignore it, and keep parsing. - Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr; - } else { - AccessorNames[Kind] = Tok.getIdentifierInfo(); - } - ConsumeToken(); - - next_property_accessor: - // Keep processing accessors until we run out. - if (TryConsumeToken(tok::comma)) - continue; - - // If we run into the ')', stop without consuming it. - if (Tok.is(tok::r_paren)) - break; - - Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen); - break; - } - - // Only add the property attribute if it was well-formed. - if (!HasInvalidAccessor) - Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(), - AccessorNames[AK_Get], AccessorNames[AK_Put], - ParsedAttr::AS_Declspec); - T.skipToEnd(); - return !HasInvalidAccessor; - } - - unsigned NumArgs = - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, - SourceLocation(), ParsedAttr::AS_Declspec); - - // If this attribute's args were parsed, and it was expected to have - // arguments but none were provided, emit a diagnostic. - if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) { - Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; - return false; - } - return true; -} - -/// [MS] decl-specifier: -/// __declspec ( extended-decl-modifier-seq ) -/// -/// [MS] extended-decl-modifier-seq: -/// extended-decl-modifier[opt] -/// extended-decl-modifier extended-decl-modifier-seq -void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, - SourceLocation *End) { - assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled"); - assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); - - while (Tok.is(tok::kw___declspec)) { - ConsumeToken(); - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", - tok::r_paren)) - return; - - // An empty declspec is perfectly legal and should not warn. Additionally, - // you can specify multiple attributes per declspec. - while (Tok.isNot(tok::r_paren)) { - // Attribute not present. - if (TryConsumeToken(tok::comma)) - continue; - - // We expect either a well-known identifier or a generic string. Anything - // else is a malformed declspec. - bool IsString = Tok.getKind() == tok::string_literal; - if (!IsString && Tok.getKind() != tok::identifier && - Tok.getKind() != tok::kw_restrict) { - Diag(Tok, diag::err_ms_declspec_type); - T.skipToEnd(); - return; - } - - IdentifierInfo *AttrName; - SourceLocation AttrNameLoc; - if (IsString) { - SmallString<8> StrBuffer; - bool Invalid = false; - StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); - if (Invalid) { - T.skipToEnd(); - return; - } - AttrName = PP.getIdentifierInfo(Str); - AttrNameLoc = ConsumeStringToken(); - } else { - AttrName = Tok.getIdentifierInfo(); - AttrNameLoc = ConsumeToken(); - } - - bool AttrHandled = false; - - // Parse attribute arguments. - if (Tok.is(tok::l_paren)) - AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); - else if (AttrName->getName() == "property") - // The property attribute must have an argument list. - Diag(Tok.getLocation(), diag::err_expected_lparen_after) - << AttrName->getName(); - - if (!AttrHandled) - Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Declspec); - } - T.consumeClose(); - if (End) - *End = T.getCloseLocation(); - } -} - -void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { - // Treat these like attributes - while (true) { - switch (Tok.getKind()) { - case tok::kw___fastcall: - case tok::kw___stdcall: - case tok::kw___thiscall: - case tok::kw___regcall: - case tok::kw___cdecl: - case tok::kw___vectorcall: - case tok::kw___ptr64: - case tok::kw___w64: - case tok::kw___ptr32: - case tok::kw___sptr: - case tok::kw___uptr: { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); - break; - } - default: - return; - } - } -} - -void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() { - SourceLocation StartLoc = Tok.getLocation(); - SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes(); - - if (EndLoc.isValid()) { - SourceRange Range(StartLoc, EndLoc); - Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range; - } -} - -SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() { - SourceLocation EndLoc; - - while (true) { - switch (Tok.getKind()) { - case tok::kw_const: - case tok::kw_volatile: - case tok::kw___fastcall: - case tok::kw___stdcall: - case tok::kw___thiscall: - case tok::kw___cdecl: - case tok::kw___vectorcall: - case tok::kw___ptr32: - case tok::kw___ptr64: - case tok::kw___w64: - case tok::kw___unaligned: - case tok::kw___sptr: - case tok::kw___uptr: - EndLoc = ConsumeToken(); - break; - default: - return EndLoc; - } - } -} - -void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { - // Treat these like attributes - while (Tok.is(tok::kw___pascal)) { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); - } -} - -void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { - // Treat these like attributes - while (Tok.is(tok::kw___kernel)) { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); - } -} - -void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = Tok.getLocation(); - Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); -} - -void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { - // Treat these like attributes, even though they're type specifiers. - while (true) { - switch (Tok.getKind()) { - case tok::kw__Nonnull: - case tok::kw__Nullable: - case tok::kw__Null_unspecified: { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - if (!getLangOpts().ObjC) - Diag(AttrNameLoc, diag::ext_nullability) - << AttrName; - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); - break; - } - default: - return; - } - } -} - -static bool VersionNumberSeparator(const char Separator) { - return (Separator == '.' || Separator == '_'); -} - -/// Parse a version number. -/// -/// version: -/// simple-integer -/// simple-integer '.' simple-integer -/// simple-integer '_' simple-integer -/// simple-integer '.' simple-integer '.' simple-integer -/// simple-integer '_' simple-integer '_' simple-integer -VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { - Range = SourceRange(Tok.getLocation(), Tok.getEndLoc()); - - if (!Tok.is(tok::numeric_constant)) { - Diag(Tok, diag::err_expected_version); - SkipUntil(tok::comma, tok::r_paren, - StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); - return VersionTuple(); - } - - // Parse the major (and possibly minor and subminor) versions, which - // are stored in the numeric constant. We utilize a quirk of the - // lexer, which is that it handles something like 1.2.3 as a single - // numeric constant, rather than two separate tokens. - SmallString<512> Buffer; - Buffer.resize(Tok.getLength()+1); - const char *ThisTokBegin = &Buffer[0]; - - // Get the spelling of the token, which eliminates trigraphs, etc. - bool Invalid = false; - unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); - if (Invalid) - return VersionTuple(); - - // Parse the major version. - unsigned AfterMajor = 0; - unsigned Major = 0; - while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) { - Major = Major * 10 + ThisTokBegin[AfterMajor] - '0'; - ++AfterMajor; - } - - if (AfterMajor == 0) { - Diag(Tok, diag::err_expected_version); - SkipUntil(tok::comma, tok::r_paren, - StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); - return VersionTuple(); - } - - if (AfterMajor == ActualLength) { - ConsumeToken(); - - // We only had a single version component. - if (Major == 0) { - Diag(Tok, diag::err_zero_version); - return VersionTuple(); - } - - return VersionTuple(Major); - } - - const char AfterMajorSeparator = ThisTokBegin[AfterMajor]; - if (!VersionNumberSeparator(AfterMajorSeparator) - || (AfterMajor + 1 == ActualLength)) { - Diag(Tok, diag::err_expected_version); - SkipUntil(tok::comma, tok::r_paren, - StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); - return VersionTuple(); - } - - // Parse the minor version. - unsigned AfterMinor = AfterMajor + 1; - unsigned Minor = 0; - while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) { - Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0'; - ++AfterMinor; - } - - if (AfterMinor == ActualLength) { - ConsumeToken(); - - // We had major.minor. - if (Major == 0 && Minor == 0) { - Diag(Tok, diag::err_zero_version); - return VersionTuple(); - } - - return VersionTuple(Major, Minor); - } - - const char AfterMinorSeparator = ThisTokBegin[AfterMinor]; - // If what follows is not a '.' or '_', we have a problem. - if (!VersionNumberSeparator(AfterMinorSeparator)) { - Diag(Tok, diag::err_expected_version); - SkipUntil(tok::comma, tok::r_paren, - StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); - return VersionTuple(); - } - - // Warn if separators, be it '.' or '_', do not match. - if (AfterMajorSeparator != AfterMinorSeparator) - Diag(Tok, diag::warn_expected_consistent_version_separator); - - // Parse the subminor version. - unsigned AfterSubminor = AfterMinor + 1; - unsigned Subminor = 0; - while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) { - Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0'; - ++AfterSubminor; - } - - if (AfterSubminor != ActualLength) { - Diag(Tok, diag::err_expected_version); - SkipUntil(tok::comma, tok::r_paren, - StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); - return VersionTuple(); - } - ConsumeToken(); - return VersionTuple(Major, Minor, Subminor); -} - -/// Parse the contents of the "availability" attribute. -/// -/// availability-attribute: -/// 'availability' '(' platform ',' opt-strict version-arg-list, -/// opt-replacement, opt-message')' -/// -/// platform: -/// identifier -/// -/// opt-strict: -/// 'strict' ',' -/// -/// version-arg-list: -/// version-arg -/// version-arg ',' version-arg-list -/// -/// version-arg: -/// 'introduced' '=' version -/// 'deprecated' '=' version -/// 'obsoleted' = version -/// 'unavailable' -/// opt-replacement: -/// 'replacement' '=' -/// opt-message: -/// 'message' '=' -void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, - SourceLocation AvailabilityLoc, - ParsedAttributes &attrs, - SourceLocation *endLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax) { - enum { Introduced, Deprecated, Obsoleted, Unknown }; - AvailabilityChange Changes[Unknown]; - ExprResult MessageExpr, ReplacementExpr; - - // Opening '('. - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.consumeOpen()) { - Diag(Tok, diag::err_expected) << tok::l_paren; - return; - } - - // Parse the platform name. - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_availability_expected_platform); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - IdentifierLoc *Platform = ParseIdentifierLoc(); - if (const IdentifierInfo *const Ident = Platform->Ident) { - // Canonicalize platform name from "macosx" to "macos". - if (Ident->getName() == "macosx") - Platform->Ident = PP.getIdentifierInfo("macos"); - // Canonicalize platform name from "macosx_app_extension" to - // "macos_app_extension". - else if (Ident->getName() == "macosx_app_extension") - Platform->Ident = PP.getIdentifierInfo("macos_app_extension"); - else - Platform->Ident = PP.getIdentifierInfo( - AvailabilityAttr::canonicalizePlatformName(Ident->getName())); - } - - // Parse the ',' following the platform name. - if (ExpectAndConsume(tok::comma)) { - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - // If we haven't grabbed the pointers for the identifiers - // "introduced", "deprecated", and "obsoleted", do so now. - if (!Ident_introduced) { - Ident_introduced = PP.getIdentifierInfo("introduced"); - Ident_deprecated = PP.getIdentifierInfo("deprecated"); - Ident_obsoleted = PP.getIdentifierInfo("obsoleted"); - Ident_unavailable = PP.getIdentifierInfo("unavailable"); - Ident_message = PP.getIdentifierInfo("message"); - Ident_strict = PP.getIdentifierInfo("strict"); - Ident_replacement = PP.getIdentifierInfo("replacement"); - } - - // Parse the optional "strict", the optional "replacement" and the set of - // introductions/deprecations/removals. - SourceLocation UnavailableLoc, StrictLoc; - do { - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_availability_expected_change); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - IdentifierInfo *Keyword = Tok.getIdentifierInfo(); - SourceLocation KeywordLoc = ConsumeToken(); - - if (Keyword == Ident_strict) { - if (StrictLoc.isValid()) { - Diag(KeywordLoc, diag::err_availability_redundant) - << Keyword << SourceRange(StrictLoc); - } - StrictLoc = KeywordLoc; - continue; - } - - if (Keyword == Ident_unavailable) { - if (UnavailableLoc.isValid()) { - Diag(KeywordLoc, diag::err_availability_redundant) - << Keyword << SourceRange(UnavailableLoc); - } - UnavailableLoc = KeywordLoc; - continue; - } - - if (Keyword == Ident_deprecated && Platform->Ident && - Platform->Ident->isStr("swift")) { - // For swift, we deprecate for all versions. - if (Changes[Deprecated].KeywordLoc.isValid()) { - Diag(KeywordLoc, diag::err_availability_redundant) - << Keyword - << SourceRange(Changes[Deprecated].KeywordLoc); - } - - Changes[Deprecated].KeywordLoc = KeywordLoc; - // Use a fake version here. - Changes[Deprecated].Version = VersionTuple(1); - continue; - } - - if (Tok.isNot(tok::equal)) { - Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - ConsumeToken(); - if (Keyword == Ident_message || Keyword == Ident_replacement) { - if (Tok.isNot(tok::string_literal)) { - Diag(Tok, diag::err_expected_string_literal) - << /*Source='availability attribute'*/2; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - if (Keyword == Ident_message) - MessageExpr = ParseStringLiteralExpression(); - else - ReplacementExpr = ParseStringLiteralExpression(); - // Also reject wide string literals. - if (StringLiteral *MessageStringLiteral = - cast_or_null(MessageExpr.get())) { - if (MessageStringLiteral->getCharByteWidth() != 1) { - Diag(MessageStringLiteral->getSourceRange().getBegin(), - diag::err_expected_string_literal) - << /*Source='availability attribute'*/ 2; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - } - if (Keyword == Ident_message) - break; - else - continue; - } - - // Special handling of 'NA' only when applied to introduced or - // deprecated. - if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) && - Tok.is(tok::identifier)) { - IdentifierInfo *NA = Tok.getIdentifierInfo(); - if (NA->getName() == "NA") { - ConsumeToken(); - if (Keyword == Ident_introduced) - UnavailableLoc = KeywordLoc; - continue; - } - } - - SourceRange VersionRange; - VersionTuple Version = ParseVersionTuple(VersionRange); - - if (Version.empty()) { - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - unsigned Index; - if (Keyword == Ident_introduced) - Index = Introduced; - else if (Keyword == Ident_deprecated) - Index = Deprecated; - else if (Keyword == Ident_obsoleted) - Index = Obsoleted; - else - Index = Unknown; - - if (Index < Unknown) { - if (!Changes[Index].KeywordLoc.isInvalid()) { - Diag(KeywordLoc, diag::err_availability_redundant) - << Keyword - << SourceRange(Changes[Index].KeywordLoc, - Changes[Index].VersionRange.getEnd()); - } - - Changes[Index].KeywordLoc = KeywordLoc; - Changes[Index].Version = Version; - Changes[Index].VersionRange = VersionRange; - } else { - Diag(KeywordLoc, diag::err_availability_unknown_change) - << Keyword << VersionRange; - } - - } while (TryConsumeToken(tok::comma)); - - // Closing ')'. - if (T.consumeClose()) - return; - - if (endLoc) - *endLoc = T.getCloseLocation(); - - // The 'unavailable' availability cannot be combined with any other - // availability changes. Make sure that hasn't happened. - if (UnavailableLoc.isValid()) { - bool Complained = false; - for (unsigned Index = Introduced; Index != Unknown; ++Index) { - if (Changes[Index].KeywordLoc.isValid()) { - if (!Complained) { - Diag(UnavailableLoc, diag::warn_availability_and_unavailable) - << SourceRange(Changes[Index].KeywordLoc, - Changes[Index].VersionRange.getEnd()); - Complained = true; - } - - // Clear out the availability. - Changes[Index] = AvailabilityChange(); - } - } - } - - // Record this attribute - attrs.addNew(&Availability, - SourceRange(AvailabilityLoc, T.getCloseLocation()), - ScopeName, ScopeLoc, - Platform, - Changes[Introduced], - Changes[Deprecated], - Changes[Obsoleted], - UnavailableLoc, MessageExpr.get(), - Syntax, StrictLoc, ReplacementExpr.get()); -} - -/// Parse the contents of the "external_source_symbol" attribute. -/// -/// external-source-symbol-attribute: -/// 'external_source_symbol' '(' keyword-arg-list ')' -/// -/// keyword-arg-list: -/// keyword-arg -/// keyword-arg ',' keyword-arg-list -/// -/// keyword-arg: -/// 'language' '=' -/// 'defined_in' '=' -/// 'generated_declaration' -void Parser::ParseExternalSourceSymbolAttribute( - IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, - ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { - // Opening '('. - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume()) - return; - - // Initialize the pointers for the keyword identifiers when required. - if (!Ident_language) { - Ident_language = PP.getIdentifierInfo("language"); - Ident_defined_in = PP.getIdentifierInfo("defined_in"); - Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration"); - } - - ExprResult Language; - bool HasLanguage = false; - ExprResult DefinedInExpr; - bool HasDefinedIn = false; - IdentifierLoc *GeneratedDeclaration = nullptr; - - // Parse the language/defined_in/generated_declaration keywords - do { - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_external_source_symbol_expected_keyword); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - SourceLocation KeywordLoc = Tok.getLocation(); - IdentifierInfo *Keyword = Tok.getIdentifierInfo(); - if (Keyword == Ident_generated_declaration) { - if (GeneratedDeclaration) { - Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - GeneratedDeclaration = ParseIdentifierLoc(); - continue; - } - - if (Keyword != Ident_language && Keyword != Ident_defined_in) { - Diag(Tok, diag::err_external_source_symbol_expected_keyword); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - ConsumeToken(); - if (ExpectAndConsume(tok::equal, diag::err_expected_after, - Keyword->getName())) { - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn; - if (Keyword == Ident_language) - HasLanguage = true; - else - HasDefinedIn = true; - - if (Tok.isNot(tok::string_literal)) { - Diag(Tok, diag::err_expected_string_literal) - << /*Source='external_source_symbol attribute'*/ 3 - << /*language | source container*/ (Keyword != Ident_language); - SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); - continue; - } - if (Keyword == Ident_language) { - if (HadLanguage) { - Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) - << Keyword; - ParseStringLiteralExpression(); - continue; - } - Language = ParseStringLiteralExpression(); - } else { - assert(Keyword == Ident_defined_in && "Invalid clause keyword!"); - if (HadDefinedIn) { - Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) - << Keyword; - ParseStringLiteralExpression(); - continue; - } - DefinedInExpr = ParseStringLiteralExpression(); - } - } while (TryConsumeToken(tok::comma)); - - // Closing ')'. - if (T.consumeClose()) - return; - if (EndLoc) - *EndLoc = T.getCloseLocation(); - - ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), - GeneratedDeclaration}; - Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()), - ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax); -} - -/// Parse the contents of the "objc_bridge_related" attribute. -/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')' -/// related_class: -/// Identifier -/// -/// opt-class_method: -/// Identifier: | -/// -/// opt-instance_method: -/// Identifier | -/// -void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, - SourceLocation ObjCBridgeRelatedLoc, - ParsedAttributes &attrs, - SourceLocation *endLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax) { - // Opening '('. - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.consumeOpen()) { - Diag(Tok, diag::err_expected) << tok::l_paren; - return; - } - - // Parse the related class name. - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_objcbridge_related_expected_related_class); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - IdentifierLoc *RelatedClass = ParseIdentifierLoc(); - if (ExpectAndConsume(tok::comma)) { - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - // Parse class method name. It's non-optional in the sense that a trailing - // comma is required, but it can be the empty string, and then we record a - // nullptr. - IdentifierLoc *ClassMethod = nullptr; - if (Tok.is(tok::identifier)) { - ClassMethod = ParseIdentifierLoc(); - if (!TryConsumeToken(tok::colon)) { - Diag(Tok, diag::err_objcbridge_related_selector_name); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - } - if (!TryConsumeToken(tok::comma)) { - if (Tok.is(tok::colon)) - Diag(Tok, diag::err_objcbridge_related_selector_name); - else - Diag(Tok, diag::err_expected) << tok::comma; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - // Parse instance method name. Also non-optional but empty string is - // permitted. - IdentifierLoc *InstanceMethod = nullptr; - if (Tok.is(tok::identifier)) - InstanceMethod = ParseIdentifierLoc(); - else if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected) << tok::r_paren; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - // Closing ')'. - if (T.consumeClose()) - return; - - if (endLoc) - *endLoc = T.getCloseLocation(); - - // Record this attribute - attrs.addNew(&ObjCBridgeRelated, - SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()), - ScopeName, ScopeLoc, - RelatedClass, - ClassMethod, - InstanceMethod, - Syntax); -} - -// Late Parsed Attributes: -// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods - -void Parser::LateParsedDeclaration::ParseLexedAttributes() {} - -void Parser::LateParsedClass::ParseLexedAttributes() { - Self->ParseLexedAttributes(*Class); -} - -void Parser::LateParsedAttribute::ParseLexedAttributes() { - Self->ParseLexedAttribute(*this, true, false); -} - -/// Wrapper class which calls ParseLexedAttribute, after setting up the -/// scope appropriately. -void Parser::ParseLexedAttributes(ParsingClass &Class) { - // Deal with templates - // FIXME: Test cases to make sure this does the right thing for templates. - bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; - ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, - HasTemplateScope); - if (HasTemplateScope) - Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); - - // Set or update the scope flags. - bool AlreadyHasClassScope = Class.TopLevelClass; - unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; - ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); - ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); - - // Enter the scope of nested classes - if (!AlreadyHasClassScope) - Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), - Class.TagOrTemplate); - if (!Class.LateParsedDeclarations.empty()) { - for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ - Class.LateParsedDeclarations[i]->ParseLexedAttributes(); - } - } - - if (!AlreadyHasClassScope) - Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), - Class.TagOrTemplate); -} - -/// Parse all attributes in LAs, and attach them to Decl D. -void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, - bool EnterScope, bool OnDefinition) { - assert(LAs.parseSoon() && - "Attribute list should be marked for immediate parsing."); - for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { - if (D) - LAs[i]->addDecl(D); - ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition); - delete LAs[i]; - } - LAs.clear(); -} - -/// Finish parsing an attribute for which parsing was delayed. -/// This will be called at the end of parsing a class declaration -/// for each LateParsedAttribute. We consume the saved tokens and -/// create an attribute with the arguments filled in. We add this -/// to the Attribute list for the decl. -void Parser::ParseLexedAttribute(LateParsedAttribute &LA, - bool EnterScope, bool OnDefinition) { - // Create a fake EOF so that attribute parsing won't go off the end of the - // attribute. - Token AttrEnd; - AttrEnd.startToken(); - AttrEnd.setKind(tok::eof); - AttrEnd.setLocation(Tok.getLocation()); - AttrEnd.setEofData(LA.Toks.data()); - LA.Toks.push_back(AttrEnd); - - // Append the current token at the end of the new token stream so that it - // doesn't get lost. - LA.Toks.push_back(Tok); - PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true); - // Consume the previously pushed token. - ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - - ParsedAttributes Attrs(AttrFactory); - SourceLocation endLoc; - - if (LA.Decls.size() > 0) { - Decl *D = LA.Decls[0]; - NamedDecl *ND = dyn_cast(D); - RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); - - // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(), - ND && ND->isCXXInstanceMember()); - - if (LA.Decls.size() == 1) { - // If the Decl is templatized, add template parameters to scope. - bool HasTemplateScope = EnterScope && D->isTemplateDecl(); - ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) - Actions.ActOnReenterTemplateScope(Actions.CurScope, D); - - // If the Decl is on a function, add function parameters to the scope. - bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); - ParseScope FnScope( - this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, - HasFunScope); - if (HasFunScope) - Actions.ActOnReenterFunctionContext(Actions.CurScope, D); - - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), ParsedAttr::AS_GNU, - nullptr); - - if (HasFunScope) { - Actions.ActOnExitFunctionContext(); - FnScope.Exit(); // Pop scope, and remove Decls from IdResolver - } - if (HasTemplateScope) { - TempScope.Exit(); - } - } else { - // If there are multiple decls, then the decl cannot be within the - // function scope. - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), ParsedAttr::AS_GNU, - nullptr); - } - } else { - Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); - } - - if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && - Attrs.begin()->isKnownToGCC()) - Diag(Tok, diag::warn_attribute_on_function_definition) - << &LA.AttrName; - - for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) - Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs); - - // Due to a parsing error, we either went over the cached tokens or - // there are still cached tokens left, so we skip the leftover tokens. - while (Tok.isNot(tok::eof)) - ConsumeAnyToken(); - - if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData()) - ConsumeAnyToken(); -} - -void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax) { - assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - - BalancedDelimiterTracker T(*this, tok::l_paren); - T.consumeOpen(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; - T.skipToEnd(); - return; - } - IdentifierLoc *ArgumentKind = ParseIdentifierLoc(); - - if (ExpectAndConsume(tok::comma)) { - T.skipToEnd(); - return; - } - - SourceRange MatchingCTypeRange; - TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange); - if (MatchingCType.isInvalid()) { - T.skipToEnd(); - return; - } - - bool LayoutCompatible = false; - bool MustBeNull = false; - while (TryConsumeToken(tok::comma)) { - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; - T.skipToEnd(); - return; - } - IdentifierInfo *Flag = Tok.getIdentifierInfo(); - if (Flag->isStr("layout_compatible")) - LayoutCompatible = true; - else if (Flag->isStr("must_be_null")) - MustBeNull = true; - else { - Diag(Tok, diag::err_type_safety_unknown_flag) << Flag; - T.skipToEnd(); - return; - } - ConsumeToken(); // consume flag - } - - if (!T.consumeClose()) { - Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc, - ArgumentKind, MatchingCType.get(), - LayoutCompatible, MustBeNull, Syntax); - } - - if (EndLoc) - *EndLoc = T.getCloseLocation(); -} - -/// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets -/// of a C++11 attribute-specifier in a location where an attribute is not -/// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this -/// situation. -/// -/// \return \c true if we skipped an attribute-like chunk of tokens, \c false if -/// this doesn't appear to actually be an attribute-specifier, and the caller -/// should try to parse it. -bool Parser::DiagnoseProhibitedCXX11Attribute() { - assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)); - - switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) { - case CAK_NotAttributeSpecifier: - // No diagnostic: we're in Obj-C++11 and this is not actually an attribute. - return false; - - case CAK_InvalidAttributeSpecifier: - Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute); - return false; - - case CAK_AttributeSpecifier: - // Parse and discard the attributes. - SourceLocation BeginLoc = ConsumeBracket(); - ConsumeBracket(); - SkipUntil(tok::r_square); - assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied"); - SourceLocation EndLoc = ConsumeBracket(); - Diag(BeginLoc, diag::err_attributes_not_allowed) - << SourceRange(BeginLoc, EndLoc); - return true; - } - llvm_unreachable("All cases handled above."); -} - -/// We have found the opening square brackets of a C++11 -/// attribute-specifier in a location where an attribute is not permitted, but -/// we know where the attributes ought to be written. Parse them anyway, and -/// provide a fixit moving them to the right place. -void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, - SourceLocation CorrectLocation) { - assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || - Tok.is(tok::kw_alignas)); - - // Consume the attributes. - SourceLocation Loc = Tok.getLocation(); - ParseCXX11Attributes(Attrs); - CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true); - // FIXME: use err_attributes_misplaced - Diag(Loc, diag::err_attributes_not_allowed) - << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) - << FixItHint::CreateRemoval(AttrRange); -} - -void Parser::DiagnoseProhibitedAttributes( - const SourceRange &Range, const SourceLocation CorrectLocation) { - if (CorrectLocation.isValid()) { - CharSourceRange AttrRange(Range, true); - Diag(CorrectLocation, diag::err_attributes_misplaced) - << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) - << FixItHint::CreateRemoval(AttrRange); - } else - Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range; -} - -void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, - unsigned DiagID) { - for (const ParsedAttr &AL : Attrs) { - if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) - continue; - if (AL.getKind() == ParsedAttr::UnknownAttribute) - Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL; - else { - Diag(AL.getLoc(), DiagID) << AL; - AL.setInvalid(); - } - } -} - -// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute -// applies to var, not the type Foo. -// As an exception to the rule, __declspec(align(...)) before the -// class-key affects the type instead of the variable. -// Also, Microsoft-style [attributes] seem to affect the type instead of the -// variable. -// This function moves attributes that should apply to the type off DS to Attrs. -void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, - DeclSpec &DS, - Sema::TagUseKind TUK) { - if (TUK == Sema::TUK_Reference) - return; - - llvm::SmallVector ToBeMoved; - - for (ParsedAttr &AL : DS.getAttributes()) { - if ((AL.getKind() == ParsedAttr::AT_Aligned && - AL.isDeclspecAttribute()) || - AL.isMicrosoftAttribute()) - ToBeMoved.push_back(&AL); - } - - for (ParsedAttr *AL : ToBeMoved) { - DS.getAttributes().remove(AL); - Attrs.addAtEnd(AL); - } -} - -/// ParseDeclaration - Parse a full 'declaration', which consists of -/// declaration-specifiers, some number of declarators, and a semicolon. -/// 'Context' should be a DeclaratorContext value. This returns the -/// location of the semicolon in DeclEnd. -/// -/// declaration: [C99 6.7] -/// block-declaration -> -/// simple-declaration -/// others [FIXME] -/// [C++] template-declaration -/// [C++] namespace-definition -/// [C++] using-directive -/// [C++] using-declaration -/// [C++11/C11] static_assert-declaration -/// others... [FIXME] -/// -Parser::DeclGroupPtrTy -Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs, - SourceLocation *DeclSpecStart) { - ParenBraceBracketBalancer BalancerRAIIObj(*this); - // Must temporarily exit the objective-c container scope for - // parsing c none objective-c decls. - ObjCDeclContextSwitch ObjCDC(*this); - - Decl *SingleDecl = nullptr; - switch (Tok.getKind()) { - case tok::kw_template: - case tok::kw_export: - ProhibitAttributes(attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs); - break; - case tok::kw_inline: - // Could be the start of an inline namespace. Allowed as an ext in C++03. - if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) { - ProhibitAttributes(attrs); - SourceLocation InlineLoc = ConsumeToken(); - return ParseNamespace(Context, DeclEnd, InlineLoc); - } - return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, - DeclSpecStart); - case tok::kw_namespace: - ProhibitAttributes(attrs); - return ParseNamespace(Context, DeclEnd); - case tok::kw_using: - return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs); - case tok::kw_static_assert: - case tok::kw__Static_assert: - ProhibitAttributes(attrs); - SingleDecl = ParseStaticAssertDeclaration(DeclEnd); - break; - default: - return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, - DeclSpecStart); - } - - // This routine returns a DeclGroup, if the thing we parsed only contains a - // single decl, convert it now. - return Actions.ConvertDeclToDeclGroup(SingleDecl); -} - -/// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] -/// declaration-specifiers init-declarator-list[opt] ';' -/// [C++11] attribute-specifier-seq decl-specifier-seq[opt] -/// init-declarator-list ';' -///[C90/C++]init-declarator-list ';' [TODO] -/// [OMP] threadprivate-directive -/// [OMP] allocate-directive [TODO] -/// -/// for-range-declaration: [C++11 6.5p1: stmt.ranged] -/// attribute-specifier-seq[opt] type-specifier-seq declarator -/// -/// If RequireSemi is false, this does not check for a ';' at the end of the -/// declaration. If it is true, it checks for and eats it. -/// -/// If FRI is non-null, we might be parsing a for-range-declaration instead -/// of a simple-declaration. If we find that we are, we also parse the -/// for-range-initializer, and place it here. -/// -/// DeclSpecStart is used when decl-specifiers are parsed before parsing -/// the Declaration. The SourceLocation for this Decl is set to -/// DeclSpecStart if DeclSpecStart is non-null. -Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( - DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI, - SourceLocation *DeclSpecStart) { - // Parse the common declaration-specifiers piece. - ParsingDeclSpec DS(*this); - - DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context); - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext); - - // If we had a free-standing type definition with a missing semicolon, we - // may get this far before the problem becomes obvious. - if (DS.hasTagDefinition() && - DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext)) - return nullptr; - - // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" - // declaration-specifiers init-declarator-list[opt] ';' - if (Tok.is(tok::semi)) { - ProhibitAttributes(Attrs); - DeclEnd = Tok.getLocation(); - if (RequireSemi) ConsumeToken(); - RecordDecl *AnonRecord = nullptr; - Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, - DS, AnonRecord); - DS.complete(TheDecl); - if (AnonRecord) { - Decl* decls[] = {AnonRecord, TheDecl}; - return Actions.BuildDeclaratorGroup(decls); - } - return Actions.ConvertDeclToDeclGroup(TheDecl); - } - - if (DeclSpecStart) - DS.SetRangeStart(*DeclSpecStart); - - DS.takeAttributesFrom(Attrs); - return ParseDeclGroup(DS, Context, &DeclEnd, FRI); -} - -/// Returns true if this might be the start of a declarator, or a common typo -/// for a declarator. -bool Parser::MightBeDeclarator(DeclaratorContext Context) { - switch (Tok.getKind()) { - case tok::annot_cxxscope: - case tok::annot_template_id: - case tok::caret: - case tok::code_completion: - case tok::coloncolon: - case tok::ellipsis: - case tok::kw___attribute: - case tok::kw_operator: - case tok::l_paren: - case tok::star: - return true; - - case tok::amp: - case tok::ampamp: - return getLangOpts().CPlusPlus; - - case tok::l_square: // Might be an attribute on an unnamed bit-field. - return Context == DeclaratorContext::MemberContext && - getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); - - case tok::colon: // Might be a typo for '::' or an unnamed bit-field. - return Context == DeclaratorContext::MemberContext || - getLangOpts().CPlusPlus; - - case tok::identifier: - switch (NextToken().getKind()) { - case tok::code_completion: - case tok::coloncolon: - case tok::comma: - case tok::equal: - case tok::equalequal: // Might be a typo for '='. - case tok::kw_alignas: - case tok::kw_asm: - case tok::kw___attribute: - case tok::l_brace: - case tok::l_paren: - case tok::l_square: - case tok::less: - case tok::r_brace: - case tok::r_paren: - case tok::r_square: - case tok::semi: - return true; - - case tok::colon: - // At namespace scope, 'identifier:' is probably a typo for 'identifier::' - // and in block scope it's probably a label. Inside a class definition, - // this is a bit-field. - return Context == DeclaratorContext::MemberContext || - (getLangOpts().CPlusPlus && - Context == DeclaratorContext::FileContext); - - case tok::identifier: // Possible virt-specifier. - return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken()); - - default: - return false; - } - - default: - return false; - } -} - -/// Skip until we reach something which seems like a sensible place to pick -/// up parsing after a malformed declaration. This will sometimes stop sooner -/// than SkipUntil(tok::r_brace) would, but will never stop later. -void Parser::SkipMalformedDecl() { - while (true) { - switch (Tok.getKind()) { - case tok::l_brace: - // Skip until matching }, then stop. We've probably skipped over - // a malformed class or function definition or similar. - ConsumeBrace(); - SkipUntil(tok::r_brace); - if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) { - // This declaration isn't over yet. Keep skipping. - continue; - } - TryConsumeToken(tok::semi); - return; - - case tok::l_square: - ConsumeBracket(); - SkipUntil(tok::r_square); - continue; - - case tok::l_paren: - ConsumeParen(); - SkipUntil(tok::r_paren); - continue; - - case tok::r_brace: - return; - - case tok::semi: - ConsumeToken(); - return; - - case tok::kw_inline: - // 'inline namespace' at the start of a line is almost certainly - // a good place to pick back up parsing, except in an Objective-C - // @interface context. - if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) && - (!ParsingInObjCContainer || CurParsedObjCImpl)) - return; - break; - - case tok::kw_namespace: - // 'namespace' at the start of a line is almost certainly a good - // place to pick back up parsing, except in an Objective-C - // @interface context. - if (Tok.isAtStartOfLine() && - (!ParsingInObjCContainer || CurParsedObjCImpl)) - return; - break; - - case tok::at: - // @end is very much like } in Objective-C contexts. - if (NextToken().isObjCAtKeyword(tok::objc_end) && - ParsingInObjCContainer) - return; - break; - - case tok::minus: - case tok::plus: - // - and + probably start new method declarations in Objective-C contexts. - if (Tok.isAtStartOfLine() && ParsingInObjCContainer) - return; - break; - - case tok::eof: - case tok::annot_module_begin: - case tok::annot_module_end: - case tok::annot_module_include: - return; - - default: - break; - } - - ConsumeAnyToken(); - } -} - -/// ParseDeclGroup - Having concluded that this is either a function -/// definition or a group of object declarations, actually parse the -/// result. -Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, - DeclaratorContext Context, - SourceLocation *DeclEnd, - ForRangeInit *FRI) { - // Parse the first declarator. - ParsingDeclarator D(*this, DS, Context); - ParseDeclarator(D); - - // Bail out if the first declarator didn't seem well-formed. - if (!D.hasName() && !D.mayOmitIdentifier()) { - SkipMalformedDecl(); - return nullptr; - } - - if (Tok.is(tok::kw_requires)) - ParseTrailingRequiresClause(D); - - // Save late-parsed attributes for now; they need to be parsed in the - // appropriate function scope after the function Decl has been constructed. - // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. - LateParsedAttrList LateParsedAttrs(true); - if (D.isFunctionDeclarator()) { - MaybeParseGNUAttributes(D, &LateParsedAttrs); - - // The _Noreturn keyword can't appear here, unlike the GNU noreturn - // attribute. If we find the keyword here, tell the user to put it - // at the start instead. - if (Tok.is(tok::kw__Noreturn)) { - SourceLocation Loc = ConsumeToken(); - const char *PrevSpec; - unsigned DiagID; - - // We can offer a fixit if it's valid to mark this function as _Noreturn - // and we don't have any other declarators in this declaration. - bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); - MaybeParseGNUAttributes(D, &LateParsedAttrs); - Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try); - - Diag(Loc, diag::err_c11_noreturn_misplaced) - << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint()) - << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ") - : FixItHint()); - } - } - - // Check to see if we have a function *definition* which must have a body. + if (D.isFunctionDeclarator() && +#ifndef noCbC + !ProtoParsing && +#endif // Look at the next token to make sure that this isn't a function // declaration. We have to check this because __attribute__ might be the // start of a function definition in GCC-extended K&R C. @@ -2135,6 +91,10 @@ bool ExpectSemi = Context != DeclaratorContext::ForContext; +#ifndef noCbC + ExpectSemi = ExpectSemi && !ProtoParsing; +#endif + // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. SourceLocation CommaLoc; @@ -3788,6 +1748,15 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy); break; +#ifndef noCbC + case tok::kw___code: { + LangOptions* LOP; + LOP = const_cast(&getLangOpts()); + LOP->HasCodeSegment = 1; + isInvalid = DS.SetTypeSpecType(DeclSpec::TST___code, Loc, PrevSpec, DiagID, Policy); + break; + } +#endif case tok::kw_char: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy); @@ -4872,6 +2841,9 @@ case tok::kw__Complex: case tok::kw__Imaginary: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw_char: case tok::kw_wchar_t: case tok::kw_char8_t: @@ -4951,6 +2923,9 @@ case tok::kw__Complex: case tok::kw__Imaginary: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw_char: case tok::kw_wchar_t: case tok::kw_char8_t: @@ -5116,6 +3091,9 @@ case tok::kw__Complex: case tok::kw__Imaginary: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw_char: case tok::kw_wchar_t: case tok::kw_char8_t: @@ -7207,6 +5185,9 @@ case tok::kw_bool: case tok::kw___bool: case tok::kw___pixel: +#ifndef noCbC + case tok::kw___code: +#endif Tok.setKind(tok::kw___vector); return true; case tok::identifier: @@ -7241,6 +5222,9 @@ case tok::kw_bool: case tok::kw___bool: case tok::kw___pixel: +#ifndef noCbC + case tok::kw___code: +#endif isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); return true; case tok::identifier: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Parse/ParseExpr.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1113,6 +1113,12 @@ } } +#ifndef noCbC + if(NeedPrototypeDeclaration(Tok)){ + CreatePrototypeDeclaration(); + } +#endif + // Consume the identifier so that we can see if it is followed by a '(' or // '.'. IdentifierInfo &II = *Tok.getIdentifierInfo(); @@ -1466,6 +1472,9 @@ case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw_typename: case tok::kw_typeof: case tok::kw___vector: @@ -1686,6 +1695,14 @@ Res = ParseObjCMessageExpression(); break; } +#ifndef noCbC + case tok::kw__CbC_return: + Res = Prepare__retForGotoWithTheEnvExpr(); + break; + case tok::kw__CbC_environment: + Res = Prepare__envForGotoWithTheEnvExpr(); + break; +#endif LLVM_FALLTHROUGH; default: NotCastExpr = true; @@ -3123,7 +3140,20 @@ if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Expr = ParseBraceInitializer(); - } else + } +#ifndef noCbC + else if (Tok.is(tok::kw__CbC_return)){ + Expr = Prepare__retForGotoWithTheEnvExpr(); + } + else if (Tok.is(tok::kw__CbC_environment)){ + Expr = Prepare__envForGotoWithTheEnvExpr(); + } + else if (Tok.is(tok::identifier) && NeedPrototypeDeclaration(Tok)){ // check code segment declaration. + CreatePrototypeDeclaration(); + Expr = ParseAssignmentExpression(); + } +#endif + else Expr = ParseAssignmentExpression(); if (Tok.is(tok::ellipsis)) diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/ParseStmt.cpp --- a/clang/lib/Parse/ParseStmt.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Parse/ParseStmt.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -266,6 +266,21 @@ return ParseForStatement(TrailingElseLoc); case tok::kw_goto: // C99 6.8.6.1: goto-statement +#ifndef noCbC + { + Token Next = NextToken(); + if (!(Next.is(tok::identifier) && PP.LookAhead(1).is(tok::semi)) && // C: 'goto' identifier ';' + Next.isNot(tok::star)) { // C: 'goto' '*' expression ';' + SemiError = "goto code segment"; + + if(Next.is(tok::identifier) && NeedPrototypeDeclaration(Next)){ // Probably, direct continuation. goto csName(); + CreatePrototypeDeclaration(); + } + + return ParseCbCGotoStatement(Attrs, Stmts); // CbC: goto codesegment statement + } + } +#endif Res = ParseGotoStatement(); SemiError = "goto"; break; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/ParseTentative.cpp --- a/clang/lib/Parse/ParseTentative.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Parse/ParseTentative.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1126,6 +1126,9 @@ case tok::kw_union: case tok::kw_unsigned: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw_volatile: case tok::kw__Bool: case tok::kw__Complex: @@ -1691,6 +1694,9 @@ case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: +#ifndef noCbC + case tok::kw___code: +#endif case tok::annot_decltype: #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" @@ -1786,6 +1792,9 @@ case tok::kw___float128: case tok::kw_void: case tok::kw___unknown_anytype: +#ifndef noCbC + case tok::kw___code: +#endif case tok::kw___auto_type: #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Parse/Parser.cpp --- a/clang/lib/Parse/Parser.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Parse/Parser.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -67,6 +67,9 @@ PP.addCommentHandler(CommentSemaHandler.get()); PP.setCodeCompletionHandler(*this); +#ifndef noCbC + UniqueId = 0; // for CreateUniqueIdentifier() +#endif } DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { @@ -583,6 +586,10 @@ if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) ConsumeToken(); +#ifndef noCbC + CheckTheSjHeader(); +#endif + Result = nullptr; switch (Tok.getKind()) { case tok::annot_pragma_unused: @@ -1346,6 +1353,9 @@ if (LateParsedAttrs) ParseLexedAttributeList(*LateParsedAttrs, Res, false, true); +#ifndef noCbC + curFuncName = D.getIdentifier()->getName().data(); +#endif return ParseFunctionStatementBody(Res, BodyScope); } diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Sema/DeclSpec.cpp --- a/clang/lib/Sema/DeclSpec.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Sema/DeclSpec.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -360,6 +360,9 @@ case TST_unspecified: case TST_void: case TST_wchar: +#ifndef noCbC + case TST___code: +#endif #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" return false; @@ -562,6 +565,9 @@ return #ImgType "_t"; #include "clang/Basic/OpenCLImageTypes.def" case DeclSpec::TST_error: return "(error)"; +#ifndef noCbC + case DeclSpec::TST___code: return "__code"; +#endif } llvm_unreachable("Unknown typespec!"); } diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Sema/SemaCodeComplete.cpp --- a/clang/lib/Sema/SemaCodeComplete.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Sema/SemaCodeComplete.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -808,6 +808,9 @@ case Type::Builtin: switch (cast(T)->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif return STC_Void; case BuiltinType::NullPtr: diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Sema/SemaTemplateVariadic.cpp --- a/clang/lib/Sema/SemaTemplateVariadic.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -884,6 +884,9 @@ #include "clang/Basic/OpenCLImageTypes.def" case TST_unknown_anytype: case TST_error: +#ifndef noCbC + case TST___code: +#endif break; } diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Sema/SemaType.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1296,6 +1296,11 @@ case DeclSpec::TST_void: Result = Context.VoidTy; break; +#ifndef noCbC + case DeclSpec::TST___code: + Result = Context.__CodeTy; + break; +#endif case DeclSpec::TST_char: if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) Result = Context.CharTy; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Serialization/ASTCommon.cpp --- a/clang/lib/Serialization/ASTCommon.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Serialization/ASTCommon.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -243,6 +243,11 @@ case BuiltinType::OMPArraySection: ID = PREDEF_TYPE_OMP_ARRAY_SECTION; break; +#ifndef noCbC + case BuiltinType::__Code: + ID = PREDEF_TYPE___CODE_ID; + break; +#endif } return TypeIdx(ID); diff -r dbda48fb9435 -r e8a9b4f4d755 clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/lib/Serialization/ASTReader.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -6740,6 +6740,11 @@ case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break; +#ifndef noCbC + case PREDEF_TYPE___CODE_ID: + T = Context.__CodeTy; + break; +#endif case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break; diff -r dbda48fb9435 -r e8a9b4f4d755 clang/tools/libclang/CIndex.cpp --- a/clang/tools/libclang/CIndex.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/clang/tools/libclang/CIndex.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1526,6 +1526,9 @@ switch (TL.getTypePtr()->getKind()) { case BuiltinType::Void: +#ifndef noCbC + case BuiltinType::__Code: +#endif case BuiltinType::NullPtr: case BuiltinType::Dependent: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/CodeGen/TargetPassConfig.h --- a/llvm/include/llvm/CodeGen/TargetPassConfig.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h Wed Mar 11 18:29:16 2020 +0900 @@ -154,6 +154,9 @@ void setInitialized() { Initialized = true; } CodeGenOpt::Level getOptLevel() const; +#ifndef noCbC + unsigned hasCodeSegment(); +#endif /// Returns true if one of the `-start-after`, `-start-before`, `-stop-after` /// or `-stop-before` options is set. diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/IR/IRBuilder.h Wed Mar 11 18:29:16 2020 +0900 @@ -429,6 +429,12 @@ return Type::getVoidTy(Context); } + #ifndef noCbC + Type *get__CodeTy() { + return Type::get__CodeTy(Context); + } +#endif + /// Fetch the type representing a pointer to an 8-bit integer value. PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { return Type::getInt8PtrTy(Context, AddrSpace); diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/IR/Type.h --- a/llvm/include/llvm/IR/Type.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/IR/Type.h Wed Mar 11 18:29:16 2020 +0900 @@ -74,6 +74,9 @@ ArrayTyID, ///< 14: Arrays PointerTyID, ///< 15: Pointers VectorTyID ///< 16: SIMD 'packed' format, or other vector type +#ifndef noCbC + ,__CodeTyID ///< 17: CbC Code Segment type +#endif }; private: @@ -137,8 +140,14 @@ /// elements defined above. TypeID getTypeID() const { return ID; } +#ifndef noCbC + bool isVoidTy() const { return (getTypeID() == VoidTyID || getTypeID() == __CodeTyID); } + /// is__CodeTy - Return true if this is '__code'. + bool is__CodeTy() const { return getTypeID() == __CodeTyID; } +#else /// Return true if this is 'void'. bool isVoidTy() const { return getTypeID() == VoidTyID; } +#endif /// Return true if this is 'half', a 16-bit IEEE fp type. bool isHalfTy() const { return getTypeID() == HalfTyID; } @@ -242,7 +251,11 @@ /// Return true if the type is "first class", meaning it is a valid type for a /// Value. bool isFirstClassType() const { +#ifndef noCbC + return getTypeID() != FunctionTyID && getTypeID() != VoidTyID && getTypeID() != __CodeTyID; +#else return getTypeID() != FunctionTyID && getTypeID() != VoidTyID; +#endif } /// Return true if the type is a valid type for a register in codegen. This @@ -416,6 +429,9 @@ static Type *getPPC_FP128Ty(LLVMContext &C); static Type *getX86_MMXTy(LLVMContext &C); static Type *getTokenTy(LLVMContext &C); +#ifndef noCbC + static Type *get__CodeTy(LLVMContext &C); // for CbC project +#endif static IntegerType *getIntNTy(LLVMContext &C, unsigned N); static IntegerType *getInt1Ty(LLVMContext &C); static IntegerType *getInt8Ty(LLVMContext &C); diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/LinkAllPasses.h --- a/llvm/include/llvm/LinkAllPasses.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/LinkAllPasses.h Wed Mar 11 18:29:16 2020 +0900 @@ -174,7 +174,11 @@ (void) llvm::createStripNonDebugSymbolsPass(); (void) llvm::createStripDeadDebugInfoPass(); (void) llvm::createStripDeadPrototypesPass(); +#ifndef noCbC + (void) llvm::createTailCallEliminationPass(false); +#else (void) llvm::createTailCallEliminationPass(); +#endif (void) llvm::createJumpThreadingPass(); (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/Target/TargetOptions.h Wed Mar 11 18:29:16 2020 +0900 @@ -287,6 +287,9 @@ /// via the llvm.fma.* intrinsic) will always be honored, regardless of /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion = FPOpFusion::Standard; +#ifndef noCbC + unsigned HasCodeSegment : 1; +#endif /// ThreadModel - This flag specifies the type of threading model to assume /// for things like atomics diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/include/llvm/Transforms/Scalar.h --- a/llvm/include/llvm/Transforms/Scalar.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/include/llvm/Transforms/Scalar.h Wed Mar 11 18:29:16 2020 +0900 @@ -121,7 +121,11 @@ // // SROA - Replace aggregates or pieces of aggregates with scalar SSA values. // +#ifndef noCbC +FunctionPass *createSROAPass(bool isOnlyForCbC = false); +#else FunctionPass *createSROAPass(); +#endif //===----------------------------------------------------------------------===// // @@ -285,7 +289,11 @@ // TailCallElimination - This pass eliminates call instructions to the current // function which occur immediately before return instructions. // +#ifndef noCbC +FunctionPass *createTailCallEliminationPass(bool isOnlyForCbC); +#else FunctionPass *createTailCallEliminationPass(); +#endif //===----------------------------------------------------------------------===// // diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -874,6 +874,9 @@ switch (T->getTypeID()) { case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break; +#ifndef noCbC + case Type::__CodeTyID: Code = bitc::TYPE_CODE_VOID; break; +#endif case Type::HalfTyID: Code = bitc::TYPE_CODE_HALF; break; case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break; case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -7246,6 +7246,35 @@ .setCallee(RetTy, FTy, Callee, std::move(Args), CS) .setTailCall(isTailCall) .setConvergent(CS.isConvergent()); +#ifndef noCbC + // variable arguments check. + if (CLI.RetTy->is__CodeTy() && CS.getCaller()->getReturnType()->is__CodeTy() && CLI.IsVarArg) { + CLI.CallConv = CallingConv::C; + errs().changeColor(raw_ostream::MAGENTA, true); + if (CS.getCalledFunction()) {// if this codesegment call is a direct access; ex) goto codesegment(); + errs() << "warning: "; + errs().resetColor(); + errs() << CS.getCaller()->getName() + " : Tail call elimination was failed on goto" + + CS.getCalledFunction()->getName() + ". Write a exactly prototype declaration.\n"; + } + else if (CS.getCalledValue()->getType()->isPointerTy()) {// if it is a pointer access; ex) goto codesegmentPointer; + errs() << "warning: "; + errs().resetColor(); + errs() << CS.getCaller()->getName() + " : Tail call elimination was failed on pointer accessed goto. Write a exactly prototype declaration.\n"; + } + } + // if code segment's tail call flag was changed false , we report it on error. + if (CLI.RetTy->is__CodeTy() && CS.getCaller()->getReturnType()->is__CodeTy() && !isTailCall && !CLI.IsVarArg) { + if (CS.getCalledFunction()) { // if this codesegment call is a direct access; ex) goto codesegment(); + errs() << "warning: " + CS.getCaller()->getName() + " : Tail call elimination was failed on goto " + + CS.getCalledFunction()->getName() + " !"; + } else if (CS.getCalledValue()->getType()->isPointerTy()) { // if it is a pointer access; ex) goto codesegmentPointer; + errs() << "warning: " + CS.getCaller()->getName() + + " : Tail call elimination was failed on codesegment which is accessed by pointer!"; // we can't get name from Type... + } + } +#endif + std::pair Result = lowerInvokable(CLI, EHPadBB); if (Result.first.getNode()) { diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -428,6 +428,12 @@ return TM->getOptLevel(); } +#ifndef noCbC +unsigned TargetPassConfig::hasCodeSegment() { + return TM->Options.HasCodeSegment; +} +#endif + /// Insert InsertedPassID pass after TargetPassID. void TargetPassConfig::insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, @@ -728,7 +734,9 @@ /// Add pass to prepare the LLVM IR for code generation. This should be done /// before exception handling preparation passes. void TargetPassConfig::addCodeGenPrepare() { +#ifdef noCbC if (getOptLevel() != CodeGenOpt::None && !DisableCGP) +#endif addPass(createCodeGenPreparePass()); addPass(createRewriteSymbolsPass()); } diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/CodeGen/ValueTypes.cpp --- a/llvm/lib/CodeGen/ValueTypes.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/CodeGen/ValueTypes.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -327,6 +327,9 @@ if (HandleUnknown) return MVT(MVT::Other); llvm_unreachable("Unknown type!"); case Type::VoidTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return MVT::isVoid; case Type::IntegerTyID: return getIntegerVT(cast(Ty)->getBitWidth()); diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp --- a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -73,6 +73,9 @@ static char getTypeID(Type *Ty) { switch (Ty->getTypeID()) { case Type::VoidTyID: return 'V'; +#ifndef noCbC + case Type::__CodeTyID: return 'V'; +#endif case Type::IntegerTyID: switch (cast(Ty)->getBitWidth()) { case 1: return 'o'; @@ -123,6 +126,9 @@ static ffi_type *ffiTypeFor(Type *Ty) { switch (Ty->getTypeID()) { case Type::VoidTyID: return &ffi_type_void; +#ifndef noCbC + case Type::__CodeTyID: return &ffi_type_void; +#endif case Type::IntegerTyID: switch (cast(Ty)->getBitWidth()) { case 8: return &ffi_type_sint8; @@ -230,7 +236,11 @@ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) == FFI_OK) { SmallVector ret; +#ifndef noCbC + if (RetTy->getTypeID() != Type::VoidTyID && RetTy->getTypeID() != Type::__CodeTyID) +#else if (RetTy->getTypeID() != Type::VoidTyID) +#endif ret.resize(TD.getTypeStoreSize(RetTy)); ffi_call(&cif, Fn, ret.data(), values.data()); switch (RetTy->getTypeID()) { diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -584,6 +584,9 @@ return rv; } case Type::VoidTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); return rv; case Type::FloatTyID: diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/IR/AsmWriter.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -560,6 +560,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) { switch (Ty->getTypeID()) { case Type::VoidTyID: OS << "void"; return; +#ifndef noCbC + case Type::__CodeTyID: OS << "void"; return; +#endif case Type::HalfTyID: OS << "half"; return; case Type::FloatTyID: OS << "float"; return; case Type::DoubleTyID: OS << "double"; return; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/IR/Core.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -474,6 +474,9 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) { switch (unwrap(Ty)->getTypeID()) { case Type::VoidTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return LLVMVoidTypeKind; case Type::HalfTyID: return LLVMHalfTypeKind; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/IR/LLVMContextImpl.cpp --- a/llvm/lib/IR/LLVMContextImpl.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/IR/LLVMContextImpl.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -34,6 +34,9 @@ FP128Ty(C, Type::FP128TyID), PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID), +#ifndef noCbC + __CodeTy(C, Type::__CodeTyID), +#endif Int1Ty(C, 1), Int8Ty(C, 8), Int16Ty(C, 16), diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/IR/LLVMContextImpl.h Wed Mar 11 18:29:16 2020 +0900 @@ -1322,6 +1322,9 @@ // Basic type instances. Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy, TokenTy; Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy; +#ifndef noCbC + Type __CodeTy; +#endif IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty; BumpPtrAllocator Alloc; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/IR/Type.cpp --- a/llvm/lib/IR/Type.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/IR/Type.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -49,6 +49,9 @@ case MetadataTyID : return getMetadataTy(C); case X86_MMXTyID : return getX86_MMXTy(C); case TokenTyID : return getTokenTy(C); +#ifndef noCbC + case __CodeTyID : return get__CodeTy(C); +#endif default: return nullptr; } @@ -173,6 +176,9 @@ Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; } Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; } Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; } +#ifndef noCbC +Type *Type::get__CodeTy(LLVMContext &C) { return &C.pImpl->__CodeTy; } +#endif IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; } IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; } diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp --- a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -330,6 +330,9 @@ case Type::MetadataTyID: case Type::X86_MMXTyID: case Type::TokenTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return 0; } diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -337,7 +337,11 @@ bool isABI = (STI.getSmVersion() >= 20); +#ifndef noCbC + if (Ty->getTypeID() == Type::VoidTyID || Ty->getTypeID() == Type::__CodeTyID) +#else if (Ty->getTypeID() == Type::VoidTyID) +#endif return; O << " ("; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1266,7 +1266,11 @@ std::stringstream O; O << "prototype_" << uniqueCallSite << " : .callprototype "; +#ifndef noCbC + if (retTy->getTypeID() == Type::VoidTyID || retTy->getTypeID() == Type::__CodeTyID) { +#else if (retTy->getTypeID() == Type::VoidTyID) { +#endif O << "()"; } else { O << "("; diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Target/XCore/XCoreISelLowering.cpp --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -1884,7 +1884,11 @@ const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I) const { +#ifndef noCbC + if (Ty->getTypeID() == Type::VoidTyID || Ty->getTypeID() == Type::__CodeTyID) +#else if (Ty->getTypeID() == Type::VoidTyID) +#endif return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); unsigned Size = DL.getTypeAllocSize(Ty); diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Transforms/IPO/PassManagerBuilder.cpp --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -285,12 +285,22 @@ if (LibraryInfo) FPM.add(new TargetLibraryInfoWrapperPass(*LibraryInfo)); +#ifndef noCbC + if (OptLevel == 0) { + FPM.add(createSROAPass(true)); + } +#else if (OptLevel == 0) return; +#endif addInitialAliasAnalysisPasses(FPM); FPM.add(createCFGSimplificationPass()); +#ifndef noCbC + FPM.add(createSROAPass(false)); +#else FPM.add(createSROAPass()); +#endif FPM.add(createEarlyCSEPass()); FPM.add(createLowerExpectIntrinsicPass()); } @@ -351,7 +361,11 @@ // Start of function pass. // Break up aggregate allocas, using SSAUpdater. assert(OptLevel >= 1 && "Calling function optimizer with no optimization level!"); +#ifndef noCbC + MPM.add(createSROAPass(false)); +#else MPM.add(createSROAPass()); +#endif MPM.add(createEarlyCSEPass(true /* Enable mem-ssa. */)); // Catch trivial redundancies if (OptLevel > 1) { @@ -385,7 +399,11 @@ // TODO: Investigate the cost/benefit of tail call elimination on debugging. if (OptLevel > 1) +#ifndef noCbC + MPM.add(createTailCallEliminationPass(false)); // CbC +#else MPM.add(createTailCallEliminationPass()); // Eliminate tail calls +#endif MPM.add(createCFGSimplificationPass()); // Merge & remove BBs MPM.add(createReassociatePass()); // Reassociate expressions @@ -503,6 +521,10 @@ else if (GlobalExtensionsNotEmpty() || !Extensions.empty()) MPM.add(createBarrierNoopPass()); +#ifndef noCbC + MPM.add(createTailCallEliminationPass(true)); // Eliminate tail calls +#endif + if (PerformThinLTO) { MPM.add(createLowerTypeTestsPass(nullptr, nullptr, true)); // Drop available_externally and unreferenced globals. This is necessary diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Transforms/Scalar/SROA.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -4624,6 +4624,13 @@ initializeSROALegacyPassPass(*PassRegistry::getPassRegistry()); } +#ifndef noCbC + SROALegacyPass(bool forCbC) : FunctionPass(ID) { + onlyForCbC = forCbC; + initializeSROALegacyPassPass(*PassRegistry::getPassRegistry()); + } +#endif + bool runOnFunction(Function &F) override { if (skipFunction(F)) return false; @@ -4641,12 +4648,21 @@ AU.setPreservesCFG(); } +#ifndef noCbC + bool onlyForCbC; + bool isOnlyForCbC() { return onlyForCbC; } +#endif + StringRef getPassName() const override { return "SROA"; } }; char SROALegacyPass::ID = 0; +#ifndef noCbC +FunctionPass *llvm::createSROAPass(bool forCbC) { return new SROALegacyPass(forCbC); } +#else FunctionPass *llvm::createSROAPass() { return new SROALegacyPass(); } +#endif INITIALIZE_PASS_BEGIN(SROALegacyPass, "sroa", "Scalar Replacement Of Aggregates", false, false) diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Transforms/Scalar/Scalar.cpp --- a/llvm/lib/Transforms/Scalar/Scalar.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Transforms/Scalar/Scalar.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -244,7 +244,11 @@ } void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM) { +#ifndef noCbC + unwrap(PM)->add(createTailCallEliminationPass(false)); +#else unwrap(PM)->add(createTailCallEliminationPass()); +#endif } void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM) { diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -206,6 +206,11 @@ bool Modified = false; +#ifndef noCbC + if (F.getReturnType()->is__CodeTy()) + Modified = markTailToCodeSegments(F); +#endif + // Track whether a block is reachable after an alloca has escaped. Blocks that // contain the escaping instruction will be marked as being visited without an // escaped alloca, since that is how the block began. @@ -816,6 +821,13 @@ initializeTailCallElimPass(*PassRegistry::getPassRegistry()); } +#ifndef noCbC + TailCallElim(bool f) : FunctionPass(ID) { + initializeTailCallElimPass(*PassRegistry::getPassRegistry()); + onlyForCbC = f; + } +#endif + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); @@ -843,6 +855,12 @@ &getAnalysis().getAAResults(), &getAnalysis().getORE(), DTU); } +#ifndef noCbC + private: + bool onlyForCbC; + public: + bool isOnlyForCbC(); +#endif }; } @@ -855,9 +873,16 @@ false, false) // Public interface to the TailCallElimination pass +#ifndef noCbC +// Public interface to the TailCallElimination pass +FunctionPass *llvm::createTailCallEliminationPass(bool isOnlyForCbC) { + return new TailCallElim(isOnlyForCbC); +} +#else FunctionPass *llvm::createTailCallEliminationPass() { return new TailCallElim(); } +#endif PreservedAnalyses TailCallElimPass::run(Function &F, FunctionAnalysisManager &AM) { @@ -881,3 +906,9 @@ PA.preserve(); return PA; } + +#ifndef noCbC +bool TailCallElim::isOnlyForCbC(){ + return onlyForCbC; +} +#endif diff -r dbda48fb9435 -r e8a9b4f4d755 llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp Fri Feb 14 15:12:50 2020 +0900 +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp Wed Mar 11 18:29:16 2020 +0900 @@ -435,6 +435,9 @@ case Type::LabelTyID: case Type::MetadataTyID: case Type::TokenTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return 0; case Type::PointerTyID: diff -r dbda48fb9435 -r e8a9b4f4d755 tools/clang/lib/Parse/CbCHelper.h --- a/tools/clang/lib/Parse/CbCHelper.h Fri Feb 14 15:12:50 2020 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#ifndef _CBC_HELPER_IS_INCLUDED -#define _CBC_HELPER_IS_INCLUDED - -#define __CBC_ENVIRONMENT_NAME "__CbC_environment" -#define __CBC_RETURN_NAME "__CbC_return" -#define __CBC_BUF_NAME "env_buf" -#define __CBC_RETVAL_NAME "retval" -#define __CBC_STRUCT_NAME "__CbC_env" -#define __CBC_STRUCT_ENV_NAME "env" -#define __CBC_STRUCT_POINTER_NAME "ret_p" -#define __CBC_RET_CODE_BASE_NAME "ret" - -#endif diff -r dbda48fb9435 -r e8a9b4f4d755 tools/clang/lib/Parse/ParseCbC.cpp --- a/tools/clang/lib/Parse/ParseCbC.cpp Fri Feb 14 15:12:50 2020 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1059 +0,0 @@ -#ifndef noCbC - -#include "clang/Parse/Parser.h" -#include "clang/Parse/RAIIObjectsForParser.h" -#include "clang/AST/ASTContext.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 "clang/Sema/SemaDiagnostic.h" - -#include -#include -#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(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()) - return !candidate.getCorrectionSpecifier() || isa(FD); - if (NextToken.is(tok::equal)) - return candidate.getCorrectionDeclAs(); - if (NextToken.is(tok::period) && - candidate.getCorrectionDeclAs()) - 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_env *)(env))->ret_p = retval; -/// longjmp((int*)(((struct __CbC_env *)env)->env),1); -/// } -ExprResult Parser::Prepare__retForGotoWithTheEnvExpr(){ - - if (isVoidFunction()) { // error check : function type is void or not. - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "continuation with the environment cannot use in the void function"); - Diag(Tok, DiagID); - return ExprError(); - } - - 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 - CreateRetCS(retcsII); - - // __code (*__CbC_return)(); - innerRes = CreateDeclStmt(__CbC_retII, true, false, DeclSpec::TST___code); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // __CbC_return = ret; - innerRes = CreateAssignmentStmt(__CbC_retII, retcsII); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // __CbC_return; - innerRes = CreateComplexStmtRet(__CbC_retII, false); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); - ConsumeToken(); // eat the '__return'. - return Actions.ActOnStmtExpr(Loc, CompoundStmtRes.get(), 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: -/// ({ -/// volatile 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(){ - - if (isVoidFunction()) { // error check : function type is void or not. - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "continuation with the environment cannot use in the void function"); - Diag(Tok, DiagID); - return ExprError(); - } - - StmtResult innerRes; - SourceLocation Loc = Tok.getLocation(); - IdentifierInfo *bufII = CreateIdentifierInfo(__CBC_BUF_NAME, Loc); - IdentifierInfo *retvalII = CreateIdentifierInfo(__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; - ExprResult Result(true); - - // struct __CbC_env __CbC_environment; - innerRes = CreateDeclStmt(__CbC_envII, false, false, DeclSpec::TST_struct, structII, DeclSpec::TQ_volatile); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // returnType retval; - innerRes = CreateDeclStmt(retvalII, false, true); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // jmp_buf env_buf; - innerRes = CreateDeclStmt(bufII, false, false, DeclSpec::TST_typename, CreateIdentifierInfo("jmp_buf", Loc)); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // __CbC_environment.ret_p = &retval; - innerRes = CreateAssignmentStmt(__CbC_envII, retvalII, true, true, ret_pII); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // __CbC_environment.env = env_buf; - innerRes = CreateAssignmentStmt(__CbC_envII, bufII, true, false, envII); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // create statements of setjmp - innerRes = CreateSjForContinuationWithTheEnv(); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - // __CbC_environment; - innerRes = CreateComplexStmtRet(__CbC_envII, true); - if (innerRes.isUsable()) - CompoundStmts.push_back(innerRes.get()); - - StmtResult CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true); - ConsumeToken(); // eat the '__environment'. - Result = Actions.ActOnStmtExpr(Loc, CompoundStmtRes.get(), Loc); - - // cast - ParsedType CastTy; - DeclSpec void_DS(AttrFactory); - setTST(&void_DS, DeclSpec::TST_void); - Declarator DeclaratorInfo(void_DS, DeclaratorContext::TypeNameContext); - DeclSpec star_DS(AttrFactory); - star_DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); - DeclaratorInfo.ExtendWithDeclSpec(star_DS); - DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); - DeclaratorInfo.AddTypeInfo(DeclaratorChunk::getPointer(star_DS.getTypeQualifiers(), Loc,star_DS.getConstSpecLoc(),star_DS.getVolatileSpecLoc(), - star_DS.getRestrictSpecLoc(),star_DS.getAtomicSpecLoc(),star_DS.getUnalignedSpecLoc()),star_DS.getAttributes(),SourceLocation()); - return Actions.ActOnCastExpr(getCurScope(), Loc, DeclaratorInfo, CastTy,Loc, Result.get()); - -} - -/// 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); - std::unique_ptr Validator(new ExternalSpace::StatementFilterCCC(Next)); - Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, LHSII, Loc, Next, false, SS.isEmpty() ? std::move(Validator) : 0); - setExprAnnotation(LHSToken, Classification.getExpression()); - LHSToken.setAnnotationEndLoc(Loc); - PP.AnnotateCachedTokens(LHSToken); - - LHS = getExprAnnotation(LHSToken); - - if (LHSisMemberAccess) - LHS = LookupMemberAndBuildExpr(extraLHSII, LHS.get(), false); - - RHS = LookupNameAndBuildExpr(RHSII); - if (RHShasAmp) - RHS = Actions.ActOnUnaryOp(getCurScope(), Loc, tok::amp, RHS.get()); - - Expr = Actions.ActOnBinOp(getCurScope(), Loc,tok::equal,LHS.get(),RHS.get()); - - 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, DeclSpec::TQ TQ){ - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - SourceLocation Loc = Tok.getLocation(); - DeclGroupPtrTy DeclGPT; - ParsingDeclSpec DS(*this); - DeclSpec *DSp; - DSp = &DS; - - setTST(&DS, valueType, Name, TQ); - ParsingDeclarator D(*this, DS, static_cast(DeclaratorContext::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(Actions, Policy); - - D.AddTypeInfo(DeclaratorChunk::getPointer(FDS.getTypeQualifiers(), Loc, FDS.getConstSpecLoc(), FDS.getVolatileSpecLoc(), - FDS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), FDS.getUnalignedSpecLoc()), FDS.getAttributes(), SourceLocation()); - D.setGroupingParens(hadGroupingParens); - - - ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope| - (D.isFunctionDeclaratorAFunctionDeclaration() ? Scope::FunctionDeclarationScope : 0)); - bool HasProto = false; - SmallVector ParamInfo; - SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, RestrictQualifierLoc; - DeclSpec FPDS(AttrFactory); - bool RefQualifierIsLValueRef = true; - ExceptionSpecificationType ESpecType = EST_None; - SourceRange ESpecRange; - SmallVector DynamicExceptions; - SmallVector DynamicExceptionRanges; - ExprResult NoexceptExpr; - CachedTokens *ExceptionSpecTokens = 0; - ParsedAttributes FnAttrs(AttrFactory); - TypeResult TrailingReturnType; - - ParmVarDecl *Param; - FunctionDecl *CurFunctionDecl = Actions.getCurFunctionDecl(); - QualType CurFuncResQT = CurFunctionDecl->getReturnType(); - 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, RefQualifierLoc, SourceLocation(), - ESpecType, ESpecRange.getBegin(), - DynamicExceptions.data(), DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, ExceptionSpecTokens, None, Loc, Loc, D, TrailingReturnType), - FnAttrs, Loc); - PrototypeScope.Exit(); - DSp = &FDS; - } - - SmallVector 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()->getReturnType(); // copy a type - TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R); // copy a type infomation - Scope *S = getCurScope(); - LookupResult Previous(Actions, NameInfo, Actions.LookupOrdinaryName, Actions.ForVisibleRedeclaration); - 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; - StmtResult InitStmt; - Sema::ConditionResult Cond; - - CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("__builtin_setjmp", Loc)); - ExprVector ArgExprs; - ExprResult __envExprRes = CondExp.get(); - - __envExprRes = LookupNameAndBuildExpr(CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc)); - __envExprRes = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc), __envExprRes.get(), false); - - ArgExprs.push_back(__envExprRes.get()); - CondExp = Actions.ActOnCallExpr(getCurScope(), CondExp.get(), Loc, ArgExprs, Loc, 0); - Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExp.get(), Sema::ConditionKind::Boolean); - - - 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(CreateIdentifierInfo(__CBC_RETVAL_NAME, Loc)); - innerStmtRes = Actions.ActOnReturnStmt(Loc, innerExprRes.get(), getCurScope()); - if (innerStmtRes.isUsable()) - innerStmts.push_back(innerStmtRes.get()); - StmtRes = Actions.ActOnCompoundStmt(Loc, Loc,innerStmts, false); - StmtResult ThenStmt(StmtRes); - InnerScope.Exit(); - IfScope.Exit(); - StmtResult ElseStmt; - IfRes = Actions.ActOnIfStmt(Loc, false, CondExp.get(), Cond, 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; - std::unique_ptr Validator(new ExternalSpace::CastExpressionIdValidator(false,true)); - Name.setIdentifier(II, Loc); - return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, false, IsAddressOfOperand, std::move(Validator)); -} - -/// LookupMemberAndBuildExpr - 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(); - CXXScopeSpec SS; - UnqualifiedId Name; - SourceLocation TemplateKWLoc; - tok::TokenKind OpKind = (IsArrow ? tok::arrow : tok::period); - Name.setIdentifier(II,Loc); - return Actions.ActOnMemberAccessExpr(getCurScope(), Base, Loc, OpKind, SS, TemplateKWLoc, Name, nullptr); -} - - -/// 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.ForVisibleRedeclaration); - 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(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(), false, false); - - 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 FieldDecls; - - FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME)); - FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_ENV_NAME)); - - Actions.ActOnFields(getCurScope(),Loc, TagDecl, FieldDecls,Loc, Loc,attrs.getList()); - StructScope.Exit(); - Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, Loc); - - 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){ - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - 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(Actions, Policy); - DeclaratorInfo.D.SetIdentifier(CreateIdentifierInfo(Name, Loc),Loc); - - DeclaratorInfo.D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,DS.getConstSpecLoc(), - DS.getVolatileSpecLoc(),DS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), - 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(TokenForII.getRawIdentifier()); - 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 : -/// current 'function name' '..' 'variable name' 'uniqueID' -/// 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 << UniqueId; - II = CreateIdentifierInfo(os.str().c_str(), Loc); - UniqueId++; // Modify the unique ID. - 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((void*)(((struct __CbC_environment *)env)->env),1); -/// } -void Parser::CreateRetCS(IdentifierInfo *csName){ - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - QualType CurFuncResQT = Actions.getCurFunctionDecl()->getReturnType(); - - 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(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(DeclaratorContext::FileContext)); - D.SetIdentifier(csName, Loc); - ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope|Scope::FunctionDeclarationScope); - bool IsAmbiguous = false; - bool HasProto = true; - SmallVector ParamInfo; - SourceLocation EllipsisLoc, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, RestrictQualifierLoc; - DeclSpec FDS(AttrFactory); - bool RefQualifierIsLValueRef = true; - ExceptionSpecificationType ESpecType = EST_None; - SourceRange ESpecRange; - SmallVector DynamicExceptions; - SmallVector DynamicExceptionRanges; - ExprResult NoexceptExpr; - CachedTokens *ExceptionSpecTokens = 0; - 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, RestrictQualifierLoc, SourceLocation(), - ESpecType, ESpecRange.getBegin(), - DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), - NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, ExceptionSpecTokens, None, - Loc, Loc, D, TrailingReturnType), FnAttrs, Loc); - PrototypeScope.Exit(); - - Decl *TheDecl; - ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); - Sema::SkipBodyInfo SkipBody; - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(); - Decl *BodyRes = Actions.ActOnStartOfFunctionDef(getCurScope(), D, - TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams : MultiTemplateParamsArg(), - &SkipBody); - - 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, DeclaratorContext::TypeNameContext); - envDInfo.SetRangeEnd(Loc); - DeclSpec starDS(AttrFactory); - starDS.Finish(Actions, Policy); - envDInfo.SetIdentifier(0,Loc); - envDInfo.AddTypeInfo(DeclaratorChunk::getPointer(starDS.getTypeQualifiers(), Loc, - starDS.getConstSpecLoc(), - starDS.getVolatileSpecLoc(), - starDS.getRestrictSpecLoc(), - starDS.getAtomicSpecLoc(), - starDS.getUnalignedSpecLoc()), - starDS.getAttributes(), - SourceLocation()); - ExprVector ArgExprs2; - LHS = LookupNameAndBuildExpr(envII); - ArgExprs2.push_back(LHS.get()); - LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs2); - Expr *envCastExpr = LHS.get(); - TypeSourceInfo *castTInfo = Actions.GetTypeForDeclaratorCast(envDInfo, envCastExpr->getType()); - LHS = Actions.MaybeConvertParenListExprToParenExpr(getCurScope(), envCastExpr); - envCastExpr = LHS.get(); - LHS = Actions.BuildCStyleCastExpr(Loc, castTInfo, Loc, envCastExpr); - ArgExprs.push_back(LHS.get()); - LHS = Actions.ActOnParenListExpr(Loc, Loc, ArgExprs); - LHS = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_POINTER_NAME, Loc), - LHS.get(), true); - Expr *ret_pCastExpr = LHS.get(); - 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.get(), RHS.get()); - innerR = Actions.ActOnExprStmt(retvalAssginmentExpr); - if(innerR.isUsable()) - FnStmts.push_back(innerR.get()); - - ExprResult ljExpr,ljLHS; - ljExpr = IIToExpr(CreateIdentifierInfo("__builtin_longjmp", Loc), tok::l_paren); - ExprVector ljArgExprs; - DeclSpec ljDS(AttrFactory); - setTST(&ljDS, DeclSpec::TST_struct, structName); - - Declarator ljD(ljDS, DeclaratorContext::TypeNameContext); - ljD.SetRangeEnd(Loc); - DeclSpec starDS2(AttrFactory); - starDS2.Finish(Actions, Policy); - ljD.ExtendWithDeclSpec(starDS2); - ljD.SetIdentifier(0, Loc); - ljD.AddTypeInfo(DeclaratorChunk::getPointer(ljDS.getTypeQualifiers(), Loc, - ljDS.getConstSpecLoc(), - ljDS.getVolatileSpecLoc(), - ljDS.getRestrictSpecLoc(), - ljDS.getAtomicSpecLoc(), - ljDS.getUnalignedSpecLoc()), - ljDS.getAttributes(), - SourceLocation()); - ljLHS = LookupNameAndBuildExpr(envII); - Expr *ljCastExpr = ljLHS.get(); - TypeSourceInfo *ljCastTInfo = Actions.GetTypeForDeclaratorCast(ljD, ljCastExpr->getType()); - ljLHS = Actions.BuildCStyleCastExpr(Loc, ljCastTInfo, Loc, ljCastExpr); - ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.get()); - ljLHS = LookupMemberAndBuildExpr(envII, ljLHS.get(), true); - ljLHS = Actions.ActOnParenExpr(Loc, Loc, ljLHS.get()); - ljArgExprs.push_back(ljLHS.get()); - CommaLocs.push_back(Loc); - ljLHS = Actions.ActOnIntegerConstant(Loc, 1 /* return value for setjmp */); - ljArgExprs.push_back(ljLHS.get()); - ljExpr = Actions.ActOnCallExpr(getCurScope(), ljExpr.get(), Loc, ljArgExprs, Loc, 0); - innerR = Actions.ActOnExprStmt(ljExpr); - if(innerR.isUsable()) - FnStmts.push_back(innerR.get()); - FnBody = Actions.ActOnCompoundStmt(Loc, Loc, FnStmts, false); - BodyScope.Exit(); - TheDecl = Actions.ActOnFinishFunctionBody(BodyRes, FnBody.get()); - returnDecl = Actions.ConvertDeclToDeclGroup(TheDecl); - (&Actions.getASTConsumer())->HandleTopLevelDecl(returnDecl.get()); - Actions.CurScope = SavedScope; - Actions.CurContext = SavedContext; - Actions.FunctionScopes.push_back(SavedFSI); -} - -/// 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); - std::unique_ptr CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); - CXXScopeSpec SS; - Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, II, Loc, Next, false, std::move(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){ - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - SourceLocation Loc = Tok.getLocation(); - DeclSpec DS(AttrFactory); - setTST(&DS, T); - Declarator ParamDeclarator(DS, DeclaratorContext::PrototypeContext); - ParamDeclarator.SetIdentifier(II, Loc); - for(int i = 0;i(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, DeclSpec::TQ TQ){ - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - SourceLocation Loc = Tok.getLocation(); - bool isInvalid = false; - const char *PrevSpec = 0; - unsigned DiagID = 0; - CXXScopeSpec SS; - DS->SetRangeStart(Loc); - DS->SetRangeEnd(Loc); - if (TQ != DeclSpec::TQ_unspecified) { - isInvalid = DS->SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, - getLangOpts()); - } - - 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(), false, false); - isInvalid = DS->SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, TagOrTempResult.get(), Owned, Policy); - } - else if (T == DeclSpec::TST_typename) { - Token Next,TypeTok; - Next.setKind(tok::identifier); - std::unique_ptr CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); - Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, Loc, Next, false, std::move(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, Policy); - } else - DS->SetTypeSpecError(); - } - else - isInvalid = DS->SetTypeSpecType(T, Loc, PrevSpec, DiagID, Policy); - - DS->Finish(Actions, Policy); - 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.ForVisibleRedeclaration); - if (!Actions.LookupName(R, getCurScope())){ // look up the setjmp - if (PP.IncludeHeader(Tok, "setjmp.h")) - ConsumeToken(); - } -} - -/// isVoidFunction - Return true if current function return type is void. -bool Parser::isVoidFunction(){ - return Actions.getCurFunctionDecl()->getReturnType().getTypePtr()->isVoidType(); -} - -/// ParseCbCGotoStatement -/// jump-statement: -/// [CbC] 'goto' codeSegment ';' -/// -StmtResult Parser::ParseCbCGotoStatement(ParsedAttributesWithRange &Attrs,StmtVector &Stmts) { - assert(Tok.is(tok::kw_goto) && "Not a goto stmt!"); - ParseScope CompoundScope(this, Scope::DeclScope); - StmtVector CompoundedStmts; - - SourceLocation gotoLoc = ConsumeToken(); // eat the 'goto'. - StmtResult gotoRes; - Token TokAfterGoto = Tok; - Stmtsp = &Stmts; - - gotoRes = ParseStatementOrDeclaration(Stmts, ACK_Any); - - if (gotoRes.get() == NULL) - return StmtError(); - else if (gotoRes.get()->getStmtClass() != Stmt::CallExprClass) { // if it is not function call - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "expected identifier or codesegment call"); - Diag(TokAfterGoto, DiagID); - return StmtError(); - } - - assert((Attrs.empty() || gotoRes.isInvalid() || gotoRes.isUsable()) && - "attributes on empty statement"); - if (!(Attrs.empty() || gotoRes.isInvalid())) - gotoRes = Actions.ProcessStmtAttributes(gotoRes.get(), Attrs.getList(), Attrs.Range); - if (gotoRes.isUsable()) - CompoundedStmts.push_back(gotoRes.get()); - - // add return; after goto codesegment(); - if (Actions.getCurFunctionDecl()->getReturnType().getTypePtr()->is__CodeType()) { - ExprResult retExpr; - StmtResult retRes; - retRes = Actions.ActOnReturnStmt(gotoLoc, retExpr.get(), getCurScope()); - if (retRes.isUsable()) - CompoundedStmts.push_back(retRes.get()); - } - return Actions.ActOnCompoundStmt(gotoLoc, Tok.getLocation(), CompoundedStmts, false); -} - -/// SearchCodeSegmentDeclaration - Read tokens until we get to the specified code segment declaration. -/// If we can't find it , return false; -bool Parser::SearchCodeSegmentDeclaration(std::string Name){ - while(SkipAnyUntil(tok::kw___code, StopBeforeMatch)){ - if(NextToken().is(tok::identifier) && NextToken().getIdentifierInfo()->getName().str() == Name) - return true; - ConsumeToken(); - } - return false; -} - -bool Parser::NeedPrototypeDeclaration(Token IITok){ - LookupResult LR(Actions, IITok.getIdentifierInfo(), IITok.getLocation(), Actions.LookupOrdinaryName); - CXXScopeSpec SS; - Actions.LookupParsedName(LR, getCurScope(), &SS, !(Actions.getCurMethodDecl())); - - return (LR.getResultKind() == LookupResult::NotFound); -} - -/// CreatePrototypeDeclaration - Create prototype declaration by it's definition. -void Parser::CreatePrototypeDeclaration(){ - // move to the top level scope - Scope *SavedScope = getCurScope(); - DeclContext *SavedContext = Actions.CurContext; - sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val(); - Actions.CurContext = static_cast(Actions.Context.getTranslationUnitDecl()); - Scope *TopScope = getCurScope(); - while(TopScope->getParent() != NULL) - TopScope = TopScope->getParent(); - Actions.CurScope = TopScope; - - Token Next = NextToken(); - Token CachedTokens[3] = {Next, PP.LookAhead(1)}; - Token SavedToken = Tok; - Token IITok = Tok.is(tok::identifier) ? Tok : Next; - PP.ClearCache(); - PP.ProtoParsing = true; - ProtoParsing = true; - - const DirectoryLookup *CurDir = nullptr; - FileID FID = PP.getSourceManager().createFileID(PP.getCurrentFileLexer()->getFileEntry(), IITok.getLocation(), SrcMgr::C_User); - PP.EnterSourceFile(FID,CurDir,IITok.getLocation()); - ConsumeToken(); - - if(SearchCodeSegmentDeclaration(IITok.getIdentifierInfo()->getName().str())){ - DeclGroupPtrTy ProtoDecl; - ParseTopLevelDecl(ProtoDecl); - // add declaration to AST. - if(ProtoDecl) - (&Actions.getASTConsumer())->HandleTopLevelDecl(ProtoDecl.get()); - // File Closing - Token T; - PP.HandleEndOfFile(T, false); - - // recover tokens. - Tok = SavedToken; - PP.RestoreTokens(CachedTokens, 2); - - } - else { - // recover tokens. - CachedTokens[2] = Tok; - Tok = SavedToken; - PP.RestoreTokens(CachedTokens, 3); - } - - // move to the previous scope. - Actions.CurScope = SavedScope; - Actions.CurContext = SavedContext; - Actions.FunctionScopes.push_back(SavedFSI); - - ProtoParsing = false; - PP.ProtoParsing = false; -} - -static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) { - return (static_cast(L) & static_cast(R)) != 0; -} - -bool Parser::SkipAnyUntil(tok::TokenKind T, SkipUntilFlags Flags){ - const PreprocessorLexer *L = PP.getCurrentFileLexer(); - while(1){ - if(Tok.is(T)){ - if (HasFlagsSet(Flags, StopBeforeMatch)) { - // Noop, don't consume the token. - } else { - ConsumeAnyToken(); - } - return true; - } - else if(PP.getCurrentFileLexer() != L){ - return false; - } - - ConsumeAnyToken(); - } -} - -#endif