Decl *Sema::ActOnImplicitEntityDecl(ASTContext &C, SMLoc IDLoc, const IdentifierInfo *IDInfo) { // FIXME: This needs to look at the IMPLICIT statements, if any. DeclSpec DS; DS.SetTypeSpecType(DeclSpec::TST_real); return ActOnEntityDecl(C, DS, IDLoc, IDInfo); }
void Sema::ActOnTypeDeclSpec(ASTContext &C, SourceLocation Loc, const IdentifierInfo *IDInfo, DeclSpec &DS) { DS.SetTypeSpecType(DeclSpec::TST_struct); auto D = ResolveIdentifier(IDInfo); if(!D) { Diags.Report(Loc, diag::err_undeclared_var_use) << IDInfo; return; } auto Record = dyn_cast<RecordDecl>(D); if(!Record) { Diags.Report(Loc, diag::err_use_of_not_typename) << IDInfo; return; } DS.setRecord(Record); }
/// ParseDeclarationTypeSpec - Parse a declaration type spec construct. /// /// [R502]: /// declaration-type-spec := /// intrinsic-type-spec /// or TYPE ( derived-type-spec ) /// or CLASS ( derived-type-spec ) /// or CLASS ( * ) bool Parser::ParseDeclarationTypeSpec(DeclSpec &DS, bool AllowSelectors, bool AllowOptionalCommaAfterCharLength) { // [R403]: // intrinsic-type-spec := // INTEGER [ kind-selector ] // or REAL [ kind-selector ] // or DOUBLE PRECISION // or COMPLEX [ kind-selector ] // or DOUBLE COMPLEX // or CHARACTER [ char-selector ] // or BYTE // or LOGICAL [ kind-selector ] switch (Tok.getKind()) { default: DS.SetTypeSpecType(DeclSpec::TST_unspecified); break; case tok::kw_INTEGER: DS.SetTypeSpecType(DeclSpec::TST_integer); break; case tok::kw_REAL: DS.SetTypeSpecType(DeclSpec::TST_real); break; case tok::kw_COMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); break; case tok::kw_CHARACTER: DS.SetTypeSpecType(DeclSpec::TST_character); break; case tok::kw_BYTE: DS.SetTypeSpecType(DeclSpec::TST_logical); DS.setByte(); // equivalent to Kind = 1 break; case tok::kw_LOGICAL: DS.SetTypeSpecType(DeclSpec::TST_logical); break; case tok::kw_DOUBLEPRECISION: DS.SetTypeSpecType(DeclSpec::TST_real); DS.setDoublePrecision(); // equivalent to Kind = 8 break; case tok::kw_DOUBLECOMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); DS.setDoublePrecision(); // equivalent to Kind = 8 break; } if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) if (ParseTypeOrClassDeclTypeSpec(DS)) return true; ExprResult Kind; ExprResult Len; // FIXME: no Kind for double complex, double precision and byte switch (DS.getTypeSpecType()) { case DeclSpec::TST_struct: break; default: ConsumeToken(); if (ConsumeIfPresent(tok::star)) { // FIXME: proper obsolete COMPLEX*16 support ConsumeAnyToken(); DS.setDoublePrecision(); } if (!AllowSelectors) break; if (ConsumeIfPresent(tok::l_paren)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; if(!ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren)) return true; } break; case DeclSpec::TST_character: // [R424]: // char-selector := // length-selector // or ( LEN = type-param-value , KIND = scalar-int-initialization-expr ) // or ( type-param-value , # // # [ KIND = ] scalar-int-initialization-expr ) // or ( KIND = scalar-int-initialization-expr [, LEN = type-param-value]) // // [R425]: // length-selector := // ( [ LEN = ] type-param-value ) // or * char-length [,] // // [R426]: // char-length := // ( type-param-value ) // or scalar-int-literal-constant // // [R402]: // type-param-value := // scalar-int-expr // or * // or : ConsumeToken(); if(ConsumeIfPresent(tok::star)) { ParseCharacterStarLengthSpec(DS); if(AllowOptionalCommaAfterCharLength) ConsumeIfPresent(tok::comma); } else { if (!AllowSelectors) break; if(ConsumeIfPresent(tok::l_paren)) { if(IsPresent(tok::kw_LEN)) { Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if(IsPresent(tok::kw_KIND)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { Len = ParseExpectedFollowupExpression("("); if(Len.isInvalid()) return true; } if(ConsumeIfPresent(tok::comma)) { // FIXME: if (Tok.is(tok::kw_LEN)) { if (Len.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple LEN selectors for this type"); Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if (Tok.is(tok::kw_KIND)) { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); ExprResult KindExpr = ParseExpression(); Kind = KindExpr; } } if(!ExpectAndConsume(tok::r_paren)) return true; } } break; } // Set the selectors for declspec. if(Kind.isUsable()) DS.setKindSelector(Kind.get()); if(Len.isUsable()) DS.setLengthSelector(Len.get()); return false; }
/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or /// a declaration. We can't tell which we have until we read up to the /// compound-statement in function-definition. TemplateParams, if /// non-NULL, provides the template parameters when we're parsing a /// C++ template-declaration. /// /// function-definition: [C99 6.9.1] /// decl-specs declarator declaration-list[opt] compound-statement /// [C90] function-definition: [C99 6.7.1] - implicit int result /// [C90] decl-specs[opt] declarator declaration-list[opt] compound-statement /// /// declaration: [C99 6.7] /// declaration-specifiers init-declarator-list[opt] ';' /// [!C99] init-declarator-list ';' [TODO: warn in c99 mode] /// [OMP] threadprivate-directive [TODO] /// Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); return Actions.ConvertDeclToDeclGroup(TheDecl); } // ObjC2 allows prefix attributes on class interfaces and protocols. // FIXME: This still needs better diagnostics. We should only accept // attributes here, no types, etc. if (getLang().ObjC2 && Tok.is(tok::at)) { SourceLocation AtLoc = ConsumeToken(); // the "@" if (!Tok.isObjCAtKeyword(tok::objc_interface) && !Tok.isObjCAtKeyword(tok::objc_protocol)) { Diag(Tok, diag::err_objc_unexpected_attr); SkipUntil(tok::semi); // FIXME: better skip? return DeclGroupPtrTy(); } const char *PrevSpec = 0; unsigned DiagID; if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID)) Diag(AtLoc, DiagID) << PrevSpec; DeclPtrTy TheDecl; if (Tok.isObjCAtKeyword(tok::objc_protocol)) TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes()); else TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); return Actions.ConvertDeclToDeclGroup(TheDecl); } // If the declspec consisted only of 'extern' and we have a string // literal following it, this must be a C++ linkage specifier like // 'extern "C"'. if (Tok.is(tok::string_literal) && getLang().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext); return Actions.ConvertDeclToDeclGroup(TheDecl); } // Parse the first declarator. Declarator DeclaratorInfo(DS, Declarator::FileContext); ParseDeclarator(DeclaratorInfo); // Error parsing the declarator? if (!DeclaratorInfo.hasName()) { // If so, skip until the semi-colon or a }. SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); return DeclGroupPtrTy(); } // If we have a declaration or declarator list, handle it. if (isDeclarationAfterDeclarator()) { // Parse the init-declarator-list for a normal declaration. DeclGroupPtrTy DG = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); // Eat the semi colon after the declaration. ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); return DG; } if (DeclaratorInfo.isFunctionDeclarator() && isStartOfFunctionDefinition()) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(Tok, diag::err_function_declared_typedef); if (Tok.is(tok::l_brace)) { // This recovery skips the entire function body. It would be nice // to simply call ParseFunctionDefinition() below, however Sema // assumes the declarator represents a function, not a typedef. ConsumeBrace(); SkipUntil(tok::r_brace, true); } else { SkipUntil(tok::semi); } return DeclGroupPtrTy(); } DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo); return Actions.ConvertDeclToDeclGroup(TheDecl); } if (DeclaratorInfo.isFunctionDeclarator()) Diag(Tok, diag::err_expected_fn_body); else Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); SkipUntil(tok::semi); return DeclGroupPtrTy(); }