//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for declarations.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Lex/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
// a constant expression of type int with a value greater than zero.
bool Sema::VerifyConstantArrayType(const ArrayType *Array,
SourceLocation DeclLoc) {
const Expr *Size = Array->getSizeExpr();
if (Size == 0) return false; // incomplete type.
if (!Size->getType()->isIntegerType()) {
Diag(Size->getLocStart(), diag::err_array_size_non_int,
Size->getType().getAsString(), Size->getSourceRange());
return true;
}
// Verify that the size of the array is an integer constant expr.
SourceLocation Loc;
llvm::APSInt SizeVal(32);
if (!Size->isIntegerConstantExpr(SizeVal, &Loc)) {
// FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
// is wrong. It is also wrong for static variables.
// FIXME: This is also wrong for:
// int sub1(int i, char *pi) { typedef int foo[i];
// struct bar {foo f1; int f2:3; int f3:4} *p; }
Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
return true;
}
// We have a constant expression with an integer type, now make sure
// value greater than zero (C99 6.7.5.2p1).
// FIXME: This check isn't specific to static VLAs, this should be moved
// elsewhere or replicated. 'int X[-1];' inside a function should emit an
// error.
if (SizeVal.isSigned()) {
llvm::APSInt Zero(SizeVal.getBitWidth());
Zero.setIsUnsigned(false);
if (SizeVal < Zero) {
Diag(DeclLoc, diag::err_typecheck_negative_array_size,
Size->getSourceRange());
return true;
} else if (SizeVal == 0) {
// GCC accepts zero sized static arrays.
Diag(DeclLoc, diag::err_typecheck_zero_array_size,
Size->getSourceRange());
}
}
return false;
}
Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
return dyn_cast_or_null<TypedefDecl>(II.getFETokenInfo<Decl>());
}
void Sema::PopScope(SourceLocation Loc, Scope *S) {
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
Decl *D = static_cast<Decl*>(*I);
assert(D && "This decl didn't get pushed??");
IdentifierInfo *II = D->getIdentifier();
if (!II) continue;
// Unlink this decl from the identifier. Because the scope contains decls
// in an unordered collection, and because we have multiple identifier
// namespaces (e.g. tag, normal, label),the decl may not be the first entry.
if (II->getFETokenInfo<Decl>() == D) {
// Normal case, no multiple decls in different namespaces.
II->setFETokenInfo(D->getNext());
} else {
// Scan ahead. There are only three namespaces in C, so this loop can
// never execute more than 3 times.
Decl *SomeDecl = II->getFETokenInfo<Decl>();
while (SomeDecl->getNext() != D) {
SomeDecl = SomeDecl->getNext();
assert(SomeDecl && "Didn't find this decl on its identifier's chain!");
}
SomeDecl->setNext(D->getNext());
}
// This will have to be revisited for C++: there we want to nest stuff in
// namespace decls etc. Even for C, we might want a top-level translation
// unit decl or something.
if (!CurFunctionDecl)
continue;
// Chain this decl to the containing function, it now owns the memory for
// the decl.
D->setNext(CurFunctionDecl->getDeclChain());
CurFunctionDecl->setDeclChain(D);
}
}
/// LookupScopedDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S) {
if (II == 0) return 0;
Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
// Scan up the scope chain looking for a decl that matches this identifier
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
for (Decl *D = II->getFETokenInfo<Decl>(); D; D = D->getNext())
if (D->getIdentifierNamespace() == NS)