Example #1
0
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);
}
Example #2
0
bool Sema::ActOnObjectArraySpec(ASTContext &C, SourceLocation Loc,
                                DeclSpec &DS,
                                ArrayRef<ArraySpec*> Dimensions) {
  if(!DS.hasAttributeSpec(DeclSpec::AS_dimension))
    DS.setAttributeSpec(DeclSpec::AS_dimension);
  DS.setDimensions(Dimensions);
  return false;
}
Example #3
0
bool Parser::ParseObjectCharLength(SourceLocation Loc, DeclSpec &DS) {
  if(DS.getTypeSpecType() == TST_character && ConsumeIfPresent(tok::star)) {
    if (DS.hasLengthSelector())
      Diag.Report(getExpectedLoc(), diag::err_duplicate_len_selector);
    return ParseCharacterStarLengthSpec(DS);
  }
  return false;
}
Example #4
0
bool Sema::ActOnAccessSpec(SourceLocation Loc, DeclSpec &DS, DeclSpec::AC Val) {
  if (DS.hasAccessSpec(Val)) {
    Diags.Report(Loc, diag::err_duplicate_access_spec)
      << DeclSpec::getSpecifierName(Val);
    return true;
  }
  DS.setAccessSpec(Val);
  return false;
}
Example #5
0
bool Sema::ActOnAttrSpec(SourceLocation Loc, DeclSpec &DS, DeclSpec::AS Val) {
  if (DS.hasAttributeSpec(Val)) {
    Diags.Report(Loc, diag::err_duplicate_attr_spec)
      << DeclSpec::getSpecifierName(Val);
    return true;
  }
  DS.setAttributeSpec(Val);
  return false;
}
Example #6
0
bool Sema::ActOnIntentSpec(SourceLocation Loc, DeclSpec &DS, DeclSpec::IS Val) {
  if (DS.hasIntentSpec(Val)) {
    Diags.Report(Loc, diag::err_duplicate_intent_spec)
      << DeclSpec::getSpecifierName(Val);
    return true;
  }
  DS.setIntentSpec(Val);
  return false;
}
Example #7
0
bool Sema::ActOnDimensionAttrSpec(ASTContext &C, SourceLocation Loc,
                                  DeclSpec &DS,
                                  ArrayRef<ArraySpec*> Dimensions) {
  if (DS.hasAttributeSpec(DeclSpec::AS_dimension)) {
    Diags.Report(Loc, diag::err_duplicate_attr_spec)
      << DeclSpec::getSpecifierName(DeclSpec::AS_dimension);
    return true;
  }
  DS.setAttributeSpec(DeclSpec::AS_dimension);
  DS.setDimensions(Dimensions);
  return false;
}
Example #8
0
bool Parser::ParseCharacterStarLengthSpec(DeclSpec &DS) {
  ExprResult Len;
  if(ConsumeIfPresent(tok::l_paren)) {
    if(ConsumeIfPresent(tok::star)) {
      DS.setStartLengthSelector();
    } else Len = ParseExpectedFollowupExpression("(");
    if(!ExpectAndConsume(tok::r_paren))
      return true;
  }
  else Len = ParseExpectedFollowupExpression("*");

  if(Len.isInvalid()) return true;
  if(Len.isUsable())  DS.setLengthSelector(Len.take());
  return false;
}
Example #9
0
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);
}
Example #10
0
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
/// template parameters (e.g., in "template<int Size> class array;").
///
///       template-parameter:
///         ...
///         parameter-declaration
Decl *
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
  // Parse the declaration-specifiers (i.e., the type).
  // FIXME: The type should probably be restricted in some way... Not all
  // declarators (parts of declarators?) are accepted for parameters.
  DeclSpec DS;
  ParseDeclarationSpecifiers(DS);

  // Parse this as a typename.
  Declarator ParamDecl(DS, Declarator::TemplateParamContext);
  ParseDeclarator(ParamDecl);
  if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
    // This probably shouldn't happen - and it's more of a Sema thing, but
    // basically we didn't parse the type name because we couldn't associate
    // it with an AST node. we should just skip to the comma or greater.
    // TODO: This is currently a placeholder for some kind of Sema Error.
    Diag(Tok.getLocation(), diag::err_parse_error);
    SkipUntil(tok::comma, tok::greater, true, true);
    return 0;
  }

  // If there is a default value, parse it.
  // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
  // we introduce the template parameter into the local scope.
  SourceLocation EqualLoc;
  ExprResult DefaultArg;
  if (Tok.is(tok::equal)) {
    EqualLoc = ConsumeToken();

    // C++ [temp.param]p15:
    //   When parsing a default template-argument for a non-type
    //   template-parameter, the first non-nested > is taken as the
    //   end of the template-parameter-list rather than a greater-than
    //   operator.
    GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);

    DefaultArg = ParseAssignmentExpression();
    if (DefaultArg.isInvalid())
      SkipUntil(tok::comma, tok::greater, true, true);
  }

  // Create the parameter.
  return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl, 
                                               Depth, Position, EqualLoc, 
                                               DefaultArg.take());
}
Example #11
0
bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
                                               const DeclSpec &DS,
                                               SourceLocation ColonColonLoc) {
  if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error)
    return true;

  assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);

  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
  if (T.isNull())
    return true;

  if (!T->isDependentType() && !T->getAs<TagType>()) {
    Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
      << T << getLangOpts().CPlusPlus;
    return true;
  }

  TypeLocBuilder TLB;
  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
  DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
  SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
            ColonColonLoc);
  return false;
}
Example #12
0
/// \brief Convert the specified DeclSpec to the appropriate type object.
QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) {
  QualType Result;
  switch (DS.getTypeSpecType()) {
  case DeclSpec::TST_integer:
    Result = C.IntegerTy;
    break;
  case DeclSpec::TST_unspecified: // FIXME: Correct?
  case DeclSpec::TST_real:
    Result = C.RealTy;
    break;
  case DeclSpec::TST_doubleprecision:
    Result = C.DoublePrecisionTy;
    break;
  case DeclSpec::TST_character:
    Result = C.CharacterTy;
    break;
  case DeclSpec::TST_logical:
    Result = C.LogicalTy;
    break;
  case DeclSpec::TST_complex:
    Result = C.ComplexTy;
    break;
  case DeclSpec::TST_struct:
    // FIXME: Finish this.
    break;
  }

  if (!DS.hasAttributes())
    return Result;

  const Type *TypeNode = Result.getTypePtr();
  Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs());
  Quals.setIntentAttr(DS.getIntentSpec());
  Quals.setAccessAttr(DS.getAccessSpec());
  QualType EQs =  C.getExtQualType(TypeNode, Quals, DS.getKindSelector(),
                                   DS.getLengthSelector());
  if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension))
    return EQs;

  return ActOnArraySpec(C, EQs, DS.getDimensions());
}
Example #13
0
/// 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();
}
Example #14
0
/// 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;
}
Example #15
0
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param DS  the declaration specifiers
/// \returns The type described by the declaration specifiers, or NULL
/// if there was an error.
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
  // FIXME: Should move the logic from DeclSpec::Finish to here for validity
  // checking.
  QualType Result;
  
  switch (DS.getTypeSpecType()) {
  case DeclSpec::TST_void:
    Result = Context.VoidTy;
    break;
  case DeclSpec::TST_char:
    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
      Result = Context.CharTy;
    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
      Result = Context.SignedCharTy;
    else {
      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
             "Unknown TSS value");
      Result = Context.UnsignedCharTy;
    }
    break;
  case DeclSpec::TST_wchar:
    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
      Result = Context.WCharTy;
    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
      Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
        << DS.getSpecifierName(DS.getTypeSpecType());
      Result = Context.getSignedWCharType();
    } else {
      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
        "Unknown TSS value");
      Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
        << DS.getSpecifierName(DS.getTypeSpecType());
      Result = Context.getUnsignedWCharType();
    }
    break;
  case DeclSpec::TST_unspecified:
    // "<proto1,proto2>" is an objc qualified ID with a missing id.
    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
      Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
                                              DS.getNumProtocolQualifiers());
      break;
    }
      
    // Unspecified typespec defaults to int in C90.  However, the C90 grammar
    // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
    // type-qualifier, or storage-class-specifier.  If not, emit an extwarn.
    // Note that the one exception to this is function definitions, which are
    // allowed to be completely missing a declspec.  This is handled in the
    // parser already though by it pretending to have seen an 'int' in this
    // case.
    if (getLangOptions().ImplicitInt) {
      // In C89 mode, we only warn if there is a completely missing declspec
      // when one is not allowed.
      if (DS.isEmpty())
        Diag(DS.getSourceRange().getBegin(), diag::warn_missing_declspec)
        << CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
                                                 "int");
    } else if (!DS.hasTypeSpecifier()) {
      // C99 and C++ require a type specifier.  For example, C99 6.7.2p2 says:
      // "At least one type specifier shall be given in the declaration
      // specifiers in each declaration, and in the specifier-qualifier list in
      // each struct declaration and type name."
      // FIXME: Does Microsoft really have the implicit int extension in C++?
      unsigned DK = getLangOptions().CPlusPlus && !getLangOptions().Microsoft?
          diag::err_missing_type_specifier
        : diag::warn_missing_type_specifier;
      Diag(DS.getSourceRange().getBegin(), DK);

      // FIXME: If we could guarantee that the result would be
      // well-formed, it would be useful to have a code insertion hint
      // here. However, after emitting this warning/error, we often
      // emit other errors.
    }
      
    // FALL THROUGH.  
  case DeclSpec::TST_int: {
    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
      switch (DS.getTypeSpecWidth()) {
      case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
      case DeclSpec::TSW_short:       Result = Context.ShortTy; break;
      case DeclSpec::TSW_long:        Result = Context.LongTy; break;
      case DeclSpec::TSW_longlong:    Result = Context.LongLongTy; break;
      }
    } else {
      switch (DS.getTypeSpecWidth()) {
      case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
      case DeclSpec::TSW_short:       Result = Context.UnsignedShortTy; break;
      case DeclSpec::TSW_long:        Result = Context.UnsignedLongTy; break;
      case DeclSpec::TSW_longlong:    Result =Context.UnsignedLongLongTy; break;
      }
    }
    break;
  }
  case DeclSpec::TST_float: Result = Context.FloatTy; break;
  case DeclSpec::TST_double:
    if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
      Result = Context.LongDoubleTy;
    else
      Result = Context.DoubleTy;
    break;
  case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
  case DeclSpec::TST_decimal32:    // _Decimal32
  case DeclSpec::TST_decimal64:    // _Decimal64
  case DeclSpec::TST_decimal128:   // _Decimal128
    assert(0 && "FIXME: GNU decimal extensions not supported yet!"); 
  case DeclSpec::TST_class:
  case DeclSpec::TST_enum:
  case DeclSpec::TST_union:
  case DeclSpec::TST_struct: {
    Decl *D = static_cast<Decl *>(DS.getTypeRep());
    assert(D && "Didn't get a decl for a class/enum/union/struct?");
    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
           DS.getTypeSpecSign() == 0 &&
           "Can't handle qualifiers on typedef names yet!");
    // TypeQuals handled by caller.
    Result = Context.getTypeDeclType(cast<TypeDecl>(D));
    break;
  }    
  case DeclSpec::TST_typename: {
    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
           DS.getTypeSpecSign() == 0 &&
           "Can't handle qualifiers on typedef names yet!");
    Result = QualType::getFromOpaquePtr(DS.getTypeRep());

    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
      // FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so
      // we have this "hack" for now... 
      if (const ObjCInterfaceType *Interface = Result->getAsObjCInterfaceType())
        Result = Context.getObjCQualifiedInterfaceType(Interface->getDecl(),
                                                       (ObjCProtocolDecl**)PQ,
                                               DS.getNumProtocolQualifiers());
      else if (Result == Context.getObjCIdType())
        // id<protocol-list>
        Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
                                                DS.getNumProtocolQualifiers());
      else if (Result == Context.getObjCClassType())
        // Class<protocol-list>
        Diag(DS.getSourceRange().getBegin(), 
             diag::err_qualified_class_unsupported) << DS.getSourceRange();
      else
        Diag(DS.getSourceRange().getBegin(),
             diag::err_invalid_protocol_qualifiers) << DS.getSourceRange();
    }
    // TypeQuals handled by caller.
    break;
  }
  case DeclSpec::TST_typeofType:
    Result = QualType::getFromOpaquePtr(DS.getTypeRep());
    assert(!Result.isNull() && "Didn't get a type for typeof?");
    // TypeQuals handled by caller.
    Result = Context.getTypeOfType(Result);
    break;
  case DeclSpec::TST_typeofExpr: {
    Expr *E = static_cast<Expr *>(DS.getTypeRep());
    assert(E && "Didn't get an expression for typeof?");
    // TypeQuals handled by caller.
    Result = Context.getTypeOfExprType(E);
    break;
  }
  case DeclSpec::TST_error:
    return QualType();
  }
  
  // Handle complex types.
  if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
    if (getLangOptions().Freestanding)
      Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
    Result = Context.getComplexType(Result);
  }
  
  assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
         "FIXME: imaginary types not supported yet!");
  
  // See if there are any attributes on the declspec that apply to the type (as
  // opposed to the decl).
  if (const AttributeList *AL = DS.getAttributes())
    ProcessTypeAttributeList(Result, AL);
    
  // Apply const/volatile/restrict qualifiers to T.
  if (unsigned TypeQuals = DS.getTypeQualifiers()) {

    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
    // or incomplete types shall not be restrict-qualified."  C++ also allows
    // restrict-qualified references.
    if (TypeQuals & QualType::Restrict) {
      if (Result->isPointerType() || Result->isReferenceType()) {
        QualType EltTy = Result->isPointerType() ? 
          Result->getAsPointerType()->getPointeeType() :
          Result->getAsReferenceType()->getPointeeType();
      
        // If we have a pointer or reference, the pointee must have an object
        // incomplete type.
        if (!EltTy->isIncompleteOrObjectType()) {
          Diag(DS.getRestrictSpecLoc(),
               diag::err_typecheck_invalid_restrict_invalid_pointee)
            << EltTy << DS.getSourceRange();
          TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
        }
      } else {
        Diag(DS.getRestrictSpecLoc(),
             diag::err_typecheck_invalid_restrict_not_pointer)
          << Result << DS.getSourceRange();
        TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
      }
    }
    
    // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
    // of a function type includes any type qualifiers, the behavior is
    // undefined."
    if (Result->isFunctionType() && TypeQuals) {
      // Get some location to point at, either the C or V location.
      SourceLocation Loc;
      if (TypeQuals & QualType::Const)
        Loc = DS.getConstSpecLoc();
      else {
        assert((TypeQuals & QualType::Volatile) &&
               "Has CV quals but not C or V?");
        Loc = DS.getVolatileSpecLoc();
      }
      Diag(Loc, diag::warn_typecheck_function_qualifiers)
        << Result << DS.getSourceRange();
    }
    
    // C++ [dcl.ref]p1:
    //   Cv-qualified references are ill-formed except when the
    //   cv-qualifiers are introduced through the use of a typedef
    //   (7.1.3) or of a template type argument (14.3), in which
    //   case the cv-qualifiers are ignored.
    // FIXME: Shouldn't we be checking SCS_typedef here?
    if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
        TypeQuals && Result->isReferenceType()) {
      TypeQuals &= ~QualType::Const;
      TypeQuals &= ~QualType::Volatile;
    }      
    
    Result = Result.getQualifiedType(TypeQuals);
  }
  return Result;
}
Example #16
0
/// \brief Convert the specified DeclSpec to the appropriate type object.
QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) {
  QualType Result;
  switch (DS.getTypeSpecType()) {
  case DeclSpec::TST_integer:
    Result = C.IntegerTy;
    break;
  case DeclSpec::TST_unspecified: // FIXME: Correct?
  case DeclSpec::TST_real:
    Result = C.RealTy;
    break;
  case DeclSpec::TST_character:
    if(DS.isStarLengthSelector())
      Result = C.NoLengthCharacterTy;
    else if(DS.hasLengthSelector())
      Result = QualType(C.getCharacterType(
                          EvalAndCheckCharacterLength(DS.getLengthSelector())), 0);
    else Result = C.CharacterTy;
    break;
  case DeclSpec::TST_logical:
    Result = C.LogicalTy;
    break;
  case DeclSpec::TST_complex:
    Result = C.ComplexTy;
    break;
  case DeclSpec::TST_struct:
    if(!DS.getRecord())
      Result = C.RealTy;
    else
      Result = C.getRecordType(DS.getRecord());
    break;
  }

  Type::TypeKind Kind = Type::NoKind;
  if(DS.hasKindSelector())
    Kind = EvalAndCheckTypeKind(Result, DS.getKindSelector());

  if(Kind != Type::NoKind || DS.isDoublePrecision() || DS.isByte()) {
    switch (DS.getTypeSpecType()) {
    case DeclSpec::TST_integer:
      Result = Kind == Type::NoKind? C.IntegerTy :
                         QualType(C.getBuiltinType(BuiltinType::Integer, Kind, true), 0);
      break;
    case DeclSpec::TST_real:
      Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoublePrecisionTy : C.RealTy) :
                         QualType(C.getBuiltinType(BuiltinType::Real, Kind, true), 0);
      break;
    case DeclSpec::TST_logical:
      Result = Kind == Type::NoKind? (DS.isByte()? C.ByteTy : C.LogicalTy) :
                         QualType(C.getBuiltinType(BuiltinType::Logical, Kind, true), 0);
      break;
    case DeclSpec::TST_complex:
      Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoubleComplexTy : C.ComplexTy) :
                         QualType(C.getBuiltinType(BuiltinType::Complex, Kind, true), 0);
      break;
    default:
      break;
    }
  }

  if (!DS.hasAttributes())
    return Result;

  const Type *TypeNode = Result.getTypePtr();
  Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs());
  Quals.setIntentAttr(DS.getIntentSpec());
  Quals.setAccessAttr(DS.getAccessSpec());

  Result = C.getExtQualType(TypeNode, Quals);

  if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension))
    return Result;

  return ActOnArraySpec(C, Result, DS.getDimensions());
}
Example #17
0
/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
/// types for a function with a K&R-style identifier list for arguments.
void Parser::ParseKNRParamDeclarations(Declarator &D) {
  // We know that the top-level of this declarator is a function.
  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;

  // Enter function-declaration scope, limiting any declarators to the
  // function prototype scope, including parameter declarators.
  ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope);

  // Read all the argument declarations.
  while (isDeclarationSpecifier()) {
    SourceLocation DSStart = Tok.getLocation();

    // Parse the common declaration-specifiers piece.
    DeclSpec DS;
    ParseDeclarationSpecifiers(DS);

    // C99 6.9.1p6: 'each declaration in the declaration list shall have at
    // least one declarator'.
    // NOTE: GCC just makes this an ext-warn.  It's not clear what it does with
    // the declarations though.  It's trivial to ignore them, really hard to do
    // anything else with them.
    if (Tok.is(tok::semi)) {
      Diag(DSStart, diag::err_declaration_does_not_declare_param);
      ConsumeToken();
      continue;
    }

    // C99 6.9.1p6: Declarations shall contain no storage-class specifiers other
    // than register.
    if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
        DS.getStorageClassSpec() != DeclSpec::SCS_register) {
      Diag(DS.getStorageClassSpecLoc(),
           diag::err_invalid_storage_class_in_func_decl);
      DS.ClearStorageClassSpecs();
    }
    if (DS.isThreadSpecified()) {
      Diag(DS.getThreadSpecLoc(),
           diag::err_invalid_storage_class_in_func_decl);
      DS.ClearStorageClassSpecs();
    }

    // Parse the first declarator attached to this declspec.
    Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
    ParseDeclarator(ParmDeclarator);

    // Handle the full declarator list.
    while (1) {
      Action::AttrTy *AttrList;
      // If attributes are present, parse them.
      if (Tok.is(tok::kw___attribute))
        // FIXME: attach attributes too.
        AttrList = ParseAttributes();

      // Ask the actions module to compute the type for this declarator.
      Action::DeclPtrTy Param =
        Actions.ActOnParamDeclarator(CurScope, ParmDeclarator);

      if (Param &&
          // A missing identifier has already been diagnosed.
          ParmDeclarator.getIdentifier()) {

        // Scan the argument list looking for the correct param to apply this
        // type.
        for (unsigned i = 0; ; ++i) {
          // C99 6.9.1p6: those declarators shall declare only identifiers from
          // the identifier list.
          if (i == FTI.NumArgs) {
            Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param)
              << ParmDeclarator.getIdentifier();
            break;
          }

          if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
            // Reject redefinitions of parameters.
            if (FTI.ArgInfo[i].Param) {
              Diag(ParmDeclarator.getIdentifierLoc(),
                   diag::err_param_redefinition)
                 << ParmDeclarator.getIdentifier();
            } else {
              FTI.ArgInfo[i].Param = Param;
            }
            break;
          }
        }
      }

      // If we don't have a comma, it is either the end of the list (a ';') or
      // an error, bail out.
      if (Tok.isNot(tok::comma))
        break;

      // Consume the comma.
      ConsumeToken();

      // Parse the next declarator.
      ParmDeclarator.clear();
      ParseDeclarator(ParmDeclarator);
    }

    if (Tok.is(tok::semi)) {
      ConsumeToken();
    } else {
      Diag(Tok, diag::err_parse_error);
      // Skip to end of block or statement
      SkipUntil(tok::semi, true);
      if (Tok.is(tok::semi))
        ConsumeToken();
    }
  }

  // The actions module must verify that all arguments were declared.
  Actions.ActOnFinishKNRParamDeclarations(CurScope, D, Tok.getLocation());
}