//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements type-related semantic analysis.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Parse/DeclSpec.h"
using namespace clang;
/// \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)
<< CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
"int");
}
// 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;
}
}