//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements decl-related attribute processing.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/DeclSpec.h"
#include <llvm/ADT/StringExtras.h>
using namespace clang;
//===----------------------------------------------------------------------===//
// Helper functions
//===----------------------------------------------------------------------===//
static const FunctionTypeProto *getFunctionProto(Decl *d) {
QualType Ty;
if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
Ty = decl->getType();
else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
Ty = decl->getType();
else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
Ty = decl->getUnderlyingType();
else
return 0;
if (Ty->isFunctionPointerType())
Ty = Ty->getAsPointerType()->getPointeeType();
if (const FunctionType *FnTy = Ty->getAsFunctionType())
return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
return 0;
}
static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
const PointerType *PT = T->getAsPointerType();
if (!PT)
return false;
const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAsObjCInterfaceType();
if (!ClsT)
return false;
IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
// FIXME: Should we walk the chain of classes?
return ClsName == &Ctx.Idents.get("NSString") ||
ClsName == &Ctx.Idents.get("NSMutableString");
}
//===----------------------------------------------------------------------===//
// Attribute Implementations
//===----------------------------------------------------------------------===//
// FIXME: All this manual attribute parsing code is gross. At the
// least add some helper functions to check most argument patterns (#
// and types of args).
static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
if (tDecl == 0) {
S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
return;
}
QualType curType = tDecl->getUnderlyingType();
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
std::string("1"));
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt vecSize(32);
if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
"ext_vector_type", sizeExpr->getSourceRange());
return;
}
// unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
if (!curType->isIntegerType() && !curType->isRealFloatingType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
curType.getAsString());
return;
}
// unlike gcc's vector_size attribute, the size is specified as the
// number of elements, not the number of bytes.
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
sizeExpr->getSourceRange());
return;
}
// Instantiate/Install the vector type, the number of elements is > 0.
tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(tDecl);
}
/// HandleVectorSizeAttribute - this attribute is only applicable to
/// integral and float scalars, although arrays, pointers, and function
/// return values are allowed in conjunction with this construct. Aggregates
/// with this attribute are invalid, even if they are of the same size as a
/// corresponding scalar.
/// The raw attribute should contain precisely 1 argument, the vector size
/// for the variable, measured in bytes. If curType and rawAttr are well
/// formed, this routine will return a new vector type.
static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
QualType