diff --git a/clang/AST/ASTContext.cpp b/clang/AST/ASTContext.cpp index b7c2deba7ab8..86d7a8e75dce 100644 --- a/clang/AST/ASTContext.cpp +++ b/clang/AST/ASTContext.cpp @@ -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(); } diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h index af88249334ec..dcd2ccab996b 100644 --- a/clang/AST/Sema.h +++ b/clang/AST/Sema.h @@ -98,7 +98,7 @@ private: TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old); FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old); VarDecl *MergeVarDecl(VarDecl *New, Decl *Old); - + /// More parsing and symbol table subroutines... VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo, Scope *FnBodyScope); diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp index e1848c40c8e3..0e5e65861e69 100644 --- a/clang/AST/SemaDecl.cpp +++ b/clang/AST/SemaDecl.cpp @@ -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,12 +197,17 @@ 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; ... - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); + // 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; } @@ -254,8 +259,19 @@ 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) { NewVD = MergeVarDecl(NewVD, PrevDecl); @@ -294,9 +310,11 @@ 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) { New->setNext(II->getFETokenInfo()); diff --git a/clang/Driver/X86Builtins.def b/clang/Driver/X86Builtins.def index 34d0745309c8..c4e3033a554c 100644 --- a/clang/Driver/X86Builtins.def +++ b/clang/Driver/X86Builtins.def @@ -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", "") diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index af88249334ec..dcd2ccab996b 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -98,7 +98,7 @@ private: TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old); FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old); VarDecl *MergeVarDecl(VarDecl *New, Decl *Old); - + /// More parsing and symbol table subroutines... VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo, Scope *FnBodyScope); diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index e1848c40c8e3..0e5e65861e69 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -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,12 +197,17 @@ 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; ... - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); + // 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; } @@ -254,8 +259,19 @@ 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) { NewVD = MergeVarDecl(NewVD, PrevDecl); @@ -294,9 +310,11 @@ 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) { New->setNext(II->getFETokenInfo()); diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 97c56bc33f49..da5871d53e1b 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -95,14 +95,21 @@ 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) { return D->getKind() == Variable || D->getKind() == Function; @@ -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; } diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e4b6b2ba83ad..36d75d7cfc0e 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -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(can) && "Invalid canonoical type"); + } friend class ASTContext; // ASTContext creates these. public: