forked from OSchip/llvm-project
Bug #:
Submitted by: Reviewed by: carbon.h looking good! Only 1 warning left...no parse errors! This fixes 3 bugs... - A couple tricky bugs with type canonicalization. Nested typedef's weren't being handled properly. For example, the following didn't work: typdef int __darwin_pid_t; typedef __darwin_pid_t pid_t; int getpgid(pid_t); int getpgid(int); - The storage class wasn't being preserved. As a result, Sema was complaining about the following: extern char *foo; char *foo; - various built-ins weren't registered...resulting in spurious warnings. llvm-svn: 39357
This commit is contained in:
parent
3273c22863
commit
6fbf0dcb6e
|
@ -15,6 +15,7 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
|
@ -268,7 +269,7 @@ TypeRef ASTContext::getTypedefType(TypedefDecl *Decl) {
|
|||
if (Decl->TypeForDecl) return Decl->TypeForDecl;
|
||||
|
||||
// FIXME: does this lose qualifiers from the typedef??
|
||||
Type *Canonical = Decl->getUnderlyingType().getTypePtr();
|
||||
Type *Canonical = Decl->getUnderlyingType().getCanonicalType().getTypePtr();
|
||||
Types.push_back(Decl->TypeForDecl = new TypedefType(Decl, Canonical));
|
||||
return Types.back();
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
|
|||
Context.Target.DiagnoseNonPortability(IdLoc,
|
||||
diag::port_target_builtin_use);
|
||||
}
|
||||
|
||||
// If this is a builtin on this (or all) targets, create the decl.
|
||||
if (unsigned BuiltinID = II->getBuiltinID())
|
||||
return LazilyCreateBuiltin(II, BuiltinID, S);
|
||||
|
@ -172,7 +171,8 @@ FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
|||
// This is not right, but it's a start. If 'Old' is a function prototype with
|
||||
// the same type as 'New', silently allow this. FIXME: We should link up decl
|
||||
// objects here.
|
||||
if (Old->getBody() == 0 && Old->getType() == New->getType()) {
|
||||
if (Old->getBody() == 0 &&
|
||||
Old->getCanonicalType() == New->getCanonicalType()) {
|
||||
return New;
|
||||
}
|
||||
|
||||
|
@ -197,14 +197,19 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
|
|||
Diag(OldD->getLocation(), diag::err_previous_definition);
|
||||
return New;
|
||||
}
|
||||
|
||||
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
|
||||
// TODO: This is totally simplistic. It should handle merging functions
|
||||
// together etc, merging extern int X; int X; ...
|
||||
// Verify the types match.
|
||||
if (Old->getCanonicalType() != New->getCanonicalType()) {
|
||||
Diag(New->getLocation(), diag::err_redefinition, New->getName());
|
||||
Diag(Old->getLocation(), diag::err_previous_definition);
|
||||
return New;
|
||||
}
|
||||
// We've verified the types match, now check if Old is "extern".
|
||||
if (Old->getStorageClass() != ObjectDecl::Extern) {
|
||||
Diag(New->getLocation(), diag::err_redefinition, New->getName());
|
||||
Diag(Old->getLocation(), diag::err_previous_definition);
|
||||
}
|
||||
return New;
|
||||
}
|
||||
|
||||
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
|
||||
/// no declarator (e.g. "struct foo;") is parsed.
|
||||
|
@ -254,7 +259,18 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
|
|||
} else {
|
||||
TypeRef R = GetTypeForDeclarator(D, S);
|
||||
if (R.isNull()) return 0;
|
||||
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R);
|
||||
|
||||
ObjectDecl::StorageClass S;
|
||||
switch (D.getDeclSpec().getStorageClassSpec()) {
|
||||
default: assert(0 && "Unknown storage class!");
|
||||
case 0: S = ObjectDecl::None;
|
||||
case DeclSpec::SCS_extern: S = ObjectDecl::Extern; break;
|
||||
case DeclSpec::SCS_static: S = ObjectDecl::Static; break;
|
||||
// The following 2 should never be seen in this context.
|
||||
case DeclSpec::SCS_auto: S = ObjectDecl::Auto; break;
|
||||
case DeclSpec::SCS_register: S = ObjectDecl::Register; break;
|
||||
}
|
||||
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, S);
|
||||
|
||||
// Merge the decl with the existing one if appropriate.
|
||||
if (PrevDecl) {
|
||||
|
@ -294,8 +310,10 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
|
|||
|
||||
}
|
||||
|
||||
// FIXME: Handle storage class (auto, register). No declarator?
|
||||
VarDecl *New = new VarDecl(PI.IdentLoc, II,
|
||||
TypeRef::getFromOpaquePtr(PI.TypeInfo));
|
||||
TypeRef::getFromOpaquePtr(PI.TypeInfo),
|
||||
ObjectDecl::None);
|
||||
|
||||
// If this has an identifier, add it to the scope stack.
|
||||
if (II) {
|
||||
|
|
|
@ -361,6 +361,14 @@ BUILTIN(__builtin_ia32_lfence, "v", "")
|
|||
BUILTIN(__builtin_ia32_mfence, "v", "")
|
||||
BUILTIN(__builtin_ia32_loaddqu, "v", "")
|
||||
BUILTIN(__builtin_ia32_storedqu, "v", "")
|
||||
BUILTIN(__builtin_ia32_psllwi, "v", "")
|
||||
BUILTIN(__builtin_ia32_pslldi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psllqi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psrawi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psradi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psrlwi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psrldi, "v", "")
|
||||
BUILTIN(__builtin_ia32_psrlqi, "v", "")
|
||||
BUILTIN(__builtin_ia32_pmuludq, "v", "")
|
||||
BUILTIN(__builtin_ia32_pmuludq128, "v", "")
|
||||
BUILTIN(__builtin_ia32_psllw128, "v", "")
|
||||
|
|
|
@ -96,7 +96,6 @@ Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
|
|||
Context.Target.DiagnoseNonPortability(IdLoc,
|
||||
diag::port_target_builtin_use);
|
||||
}
|
||||
|
||||
// If this is a builtin on this (or all) targets, create the decl.
|
||||
if (unsigned BuiltinID = II->getBuiltinID())
|
||||
return LazilyCreateBuiltin(II, BuiltinID, S);
|
||||
|
@ -172,7 +171,8 @@ FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
|||
// This is not right, but it's a start. If 'Old' is a function prototype with
|
||||
// the same type as 'New', silently allow this. FIXME: We should link up decl
|
||||
// objects here.
|
||||
if (Old->getBody() == 0 && Old->getType() == New->getType()) {
|
||||
if (Old->getBody() == 0 &&
|
||||
Old->getCanonicalType() == New->getCanonicalType()) {
|
||||
return New;
|
||||
}
|
||||
|
||||
|
@ -197,14 +197,19 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
|
|||
Diag(OldD->getLocation(), diag::err_previous_definition);
|
||||
return New;
|
||||
}
|
||||
|
||||
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
|
||||
// TODO: This is totally simplistic. It should handle merging functions
|
||||
// together etc, merging extern int X; int X; ...
|
||||
// Verify the types match.
|
||||
if (Old->getCanonicalType() != New->getCanonicalType()) {
|
||||
Diag(New->getLocation(), diag::err_redefinition, New->getName());
|
||||
Diag(Old->getLocation(), diag::err_previous_definition);
|
||||
return New;
|
||||
}
|
||||
// We've verified the types match, now check if Old is "extern".
|
||||
if (Old->getStorageClass() != ObjectDecl::Extern) {
|
||||
Diag(New->getLocation(), diag::err_redefinition, New->getName());
|
||||
Diag(Old->getLocation(), diag::err_previous_definition);
|
||||
}
|
||||
return New;
|
||||
}
|
||||
|
||||
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
|
||||
/// no declarator (e.g. "struct foo;") is parsed.
|
||||
|
@ -254,7 +259,18 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
|
|||
} else {
|
||||
TypeRef R = GetTypeForDeclarator(D, S);
|
||||
if (R.isNull()) return 0;
|
||||
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R);
|
||||
|
||||
ObjectDecl::StorageClass S;
|
||||
switch (D.getDeclSpec().getStorageClassSpec()) {
|
||||
default: assert(0 && "Unknown storage class!");
|
||||
case 0: S = ObjectDecl::None;
|
||||
case DeclSpec::SCS_extern: S = ObjectDecl::Extern; break;
|
||||
case DeclSpec::SCS_static: S = ObjectDecl::Static; break;
|
||||
// The following 2 should never be seen in this context.
|
||||
case DeclSpec::SCS_auto: S = ObjectDecl::Auto; break;
|
||||
case DeclSpec::SCS_register: S = ObjectDecl::Register; break;
|
||||
}
|
||||
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, S);
|
||||
|
||||
// Merge the decl with the existing one if appropriate.
|
||||
if (PrevDecl) {
|
||||
|
@ -294,8 +310,10 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
|
|||
|
||||
}
|
||||
|
||||
// FIXME: Handle storage class (auto, register). No declarator?
|
||||
VarDecl *New = new VarDecl(PI.IdentLoc, II,
|
||||
TypeRef::getFromOpaquePtr(PI.TypeInfo));
|
||||
TypeRef::getFromOpaquePtr(PI.TypeInfo),
|
||||
ObjectDecl::None);
|
||||
|
||||
// If this has an identifier, add it to the scope stack.
|
||||
if (II) {
|
||||
|
|
|
@ -95,13 +95,20 @@ public:
|
|||
|
||||
/// ObjectDecl - Represents a declaration of a value.
|
||||
class ObjectDecl : public Decl {
|
||||
TypeRef DeclType;
|
||||
protected:
|
||||
ObjectDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T)
|
||||
: Decl(DK, L, Id), DeclType(T) {}
|
||||
public:
|
||||
|
||||
enum StorageClass {
|
||||
None, Extern, Static, Auto, Register
|
||||
};
|
||||
private:
|
||||
TypeRef DeclType;
|
||||
StorageClass SClass;
|
||||
protected:
|
||||
ObjectDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T,
|
||||
StorageClass S = None): Decl(DK, L, Id), DeclType(T), SClass(S) {}
|
||||
public:
|
||||
TypeRef getType() const { return DeclType; }
|
||||
TypeRef getCanonicalType() const { return DeclType.getCanonicalType(); }
|
||||
StorageClass getStorageClass() const { return SClass; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
|
@ -115,8 +122,8 @@ public:
|
|||
class VarDecl : public ObjectDecl {
|
||||
// TODO: Initializer.
|
||||
public:
|
||||
VarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
|
||||
: ObjectDecl(Variable, L, Id, T) {}
|
||||
VarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S)
|
||||
: ObjectDecl(Variable, L, Id, T, S) {}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Variable; }
|
||||
|
|
|
@ -302,7 +302,7 @@ public:
|
|||
static bool classof(const ArrayType *) { return true; }
|
||||
};
|
||||
|
||||
/// FunctionType - C99 6.7.5.3 - Array Declarators. This is the common base
|
||||
/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base
|
||||
/// class of FunctionTypeNoProto and FunctionTypeProto.
|
||||
///
|
||||
class FunctionType : public Type {
|
||||
|
@ -396,7 +396,9 @@ public:
|
|||
|
||||
class TypedefType : public Type {
|
||||
TypedefDecl *Decl;
|
||||
TypedefType(TypedefDecl *D, Type *can) : Type(TypeName, can), Decl(D) {}
|
||||
TypedefType(TypedefDecl *D, Type *can) : Type(TypeName, can), Decl(D) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonoical type");
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
|
Loading…
Reference in New Issue