| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by Chris Lattner and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | //  This file implements semantic analysis for declarations. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "Sema.h" | 
|  | 15 | #include "clang/AST/ASTContext.h" | 
|  | 16 | #include "clang/AST/Builtins.h" | 
|  | 17 | #include "clang/AST/Decl.h" | 
|  | 18 | #include "clang/AST/Expr.h" | 
|  | 19 | #include "clang/AST/Type.h" | 
|  | 20 | #include "clang/Parse/DeclSpec.h" | 
|  | 21 | #include "clang/Parse/Scope.h" | 
|  | 22 | #include "clang/Lex/IdentifierTable.h" | 
|  | 23 | #include "clang/Basic/LangOptions.h" | 
|  | 24 | #include "clang/Basic/TargetInfo.h" | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 25 | #include "llvm/ADT/SmallString.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/SmallSet.h" | 
|  | 27 | using namespace clang; | 
|  | 28 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 29 | Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 30 | Decl *IIDecl = II.getFETokenInfo<Decl>(); | 
|  | 31 | if (dyn_cast_or_null<TypedefDecl>(IIDecl) || | 
| Fariborz Jahanian | fd225cc | 2007-09-18 20:26:58 +0000 | [diff] [blame] | 32 | dyn_cast_or_null<ObjcInterfaceDecl>(IIDecl)) | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 33 | return IIDecl; | 
|  | 34 | return 0; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 35 | } | 
|  | 36 |  | 
|  | 37 | void Sema::PopScope(SourceLocation Loc, Scope *S) { | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 38 | if (S->decl_empty()) return; | 
|  | 39 | assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!"); | 
|  | 40 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 41 | for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); | 
|  | 42 | I != E; ++I) { | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 43 | Decl *TmpD = static_cast<Decl*>(*I); | 
|  | 44 | assert(TmpD && "This decl didn't get pushed??"); | 
|  | 45 | ScopedDecl *D = dyn_cast<ScopedDecl>(TmpD); | 
|  | 46 | assert(D && "This decl isn't a ScopedDecl?"); | 
|  | 47 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 48 | IdentifierInfo *II = D->getIdentifier(); | 
|  | 49 | if (!II) continue; | 
|  | 50 |  | 
|  | 51 | // Unlink this decl from the identifier.  Because the scope contains decls | 
|  | 52 | // in an unordered collection, and because we have multiple identifier | 
|  | 53 | // namespaces (e.g. tag, normal, label),the decl may not be the first entry. | 
|  | 54 | if (II->getFETokenInfo<Decl>() == D) { | 
|  | 55 | // Normal case, no multiple decls in different namespaces. | 
|  | 56 | II->setFETokenInfo(D->getNext()); | 
|  | 57 | } else { | 
|  | 58 | // Scan ahead.  There are only three namespaces in C, so this loop can | 
|  | 59 | // never execute more than 3 times. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 60 | ScopedDecl *SomeDecl = II->getFETokenInfo<ScopedDecl>(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 61 | while (SomeDecl->getNext() != D) { | 
|  | 62 | SomeDecl = SomeDecl->getNext(); | 
|  | 63 | assert(SomeDecl && "Didn't find this decl on its identifier's chain!"); | 
|  | 64 | } | 
|  | 65 | SomeDecl->setNext(D->getNext()); | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | // This will have to be revisited for C++: there we want to nest stuff in | 
|  | 69 | // namespace decls etc.  Even for C, we might want a top-level translation | 
|  | 70 | // unit decl or something. | 
|  | 71 | if (!CurFunctionDecl) | 
|  | 72 | continue; | 
|  | 73 |  | 
|  | 74 | // Chain this decl to the containing function, it now owns the memory for | 
|  | 75 | // the decl. | 
|  | 76 | D->setNext(CurFunctionDecl->getDeclChain()); | 
|  | 77 | CurFunctionDecl->setDeclChain(D); | 
|  | 78 | } | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | /// LookupScopedDecl - Look up the inner-most declaration in the specified | 
|  | 82 | /// namespace. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 83 | ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI, | 
|  | 84 | SourceLocation IdLoc, Scope *S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 85 | if (II == 0) return 0; | 
|  | 86 | Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI; | 
|  | 87 |  | 
|  | 88 | // Scan up the scope chain looking for a decl that matches this identifier | 
|  | 89 | // that is in the appropriate namespace.  This search should not take long, as | 
|  | 90 | // shadowing of names is uncommon, and deep shadowing is extremely uncommon. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 91 | for (ScopedDecl *D = II->getFETokenInfo<ScopedDecl>(); D; D = D->getNext()) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 92 | if (D->getIdentifierNamespace() == NS) | 
|  | 93 | return D; | 
|  | 94 |  | 
|  | 95 | // If we didn't find a use of this identifier, and if the identifier | 
|  | 96 | // corresponds to a compiler builtin, create the decl object for the builtin | 
|  | 97 | // now, injecting it into translation unit scope, and return it. | 
|  | 98 | if (NS == Decl::IDNS_Ordinary) { | 
|  | 99 | // If this is a builtin on some other target, or if this builtin varies | 
|  | 100 | // across targets (e.g. in type), emit a diagnostic and mark the translation | 
|  | 101 | // unit non-portable for using it. | 
|  | 102 | if (II->isNonPortableBuiltin()) { | 
|  | 103 | // Only emit this diagnostic once for this builtin. | 
|  | 104 | II->setNonPortableBuiltin(false); | 
|  | 105 | Context.Target.DiagnoseNonPortability(IdLoc, | 
|  | 106 | diag::port_target_builtin_use); | 
|  | 107 | } | 
|  | 108 | // If this is a builtin on this (or all) targets, create the decl. | 
|  | 109 | if (unsigned BuiltinID = II->getBuiltinID()) | 
|  | 110 | return LazilyCreateBuiltin(II, BuiltinID, S); | 
|  | 111 | } | 
|  | 112 | return 0; | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | /// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope. | 
|  | 116 | /// lazily create a decl for it. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 117 | ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 118 | Builtin::ID BID = (Builtin::ID)bid; | 
|  | 119 |  | 
|  | 120 | QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context); | 
|  | 121 | FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R, | 
| Chris Lattner | 70c8b2e | 2007-08-26 04:02:13 +0000 | [diff] [blame] | 122 | FunctionDecl::Extern, false, 0); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 123 |  | 
|  | 124 | // Find translation-unit scope to insert this function into. | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 125 | if (Scope *FnS = S->getFnParent()) | 
|  | 126 | S = FnS->getParent();   // Skip all scopes in a function at once. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 127 | while (S->getParent()) | 
|  | 128 | S = S->getParent(); | 
|  | 129 | S->AddDecl(New); | 
|  | 130 |  | 
|  | 131 | // Add this decl to the end of the identifier info. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 132 | if (ScopedDecl *LastDecl = II->getFETokenInfo<ScopedDecl>()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 133 | // Scan until we find the last (outermost) decl in the id chain. | 
|  | 134 | while (LastDecl->getNext()) | 
|  | 135 | LastDecl = LastDecl->getNext(); | 
|  | 136 | // Insert before (outside) it. | 
|  | 137 | LastDecl->setNext(New); | 
|  | 138 | } else { | 
|  | 139 | II->setFETokenInfo(New); | 
|  | 140 | } | 
|  | 141 | // Make sure clients iterating over decls see this. | 
|  | 142 | LastInGroupList.push_back(New); | 
|  | 143 |  | 
|  | 144 | return New; | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | /// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name | 
|  | 148 | /// and scope as a previous declaration 'Old'.  Figure out how to resolve this | 
|  | 149 | /// situation, merging decls or emitting diagnostics as appropriate. | 
|  | 150 | /// | 
| Steve Naroff | 8e74c93 | 2007-09-13 21:41:19 +0000 | [diff] [blame] | 151 | TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *OldD) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 152 | // Verify the old decl was also a typedef. | 
|  | 153 | TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD); | 
|  | 154 | if (!Old) { | 
|  | 155 | Diag(New->getLocation(), diag::err_redefinition_different_kind, | 
|  | 156 | New->getName()); | 
|  | 157 | Diag(OldD->getLocation(), diag::err_previous_definition); | 
|  | 158 | return New; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. | 
|  | 162 | // TODO: This is totally simplistic.  It should handle merging functions | 
|  | 163 | // together etc, merging extern int X; int X; ... | 
|  | 164 | Diag(New->getLocation(), diag::err_redefinition, New->getName()); | 
|  | 165 | Diag(Old->getLocation(), diag::err_previous_definition); | 
|  | 166 | return New; | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | /// MergeFunctionDecl - We just parsed a function 'New' which has the same name | 
|  | 170 | /// and scope as a previous declaration 'Old'.  Figure out how to resolve this | 
|  | 171 | /// situation, merging decls or emitting diagnostics as appropriate. | 
|  | 172 | /// | 
| Steve Naroff | 8e74c93 | 2007-09-13 21:41:19 +0000 | [diff] [blame] | 173 | FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, ScopedDecl *OldD) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 174 | // Verify the old decl was also a function. | 
|  | 175 | FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD); | 
|  | 176 | if (!Old) { | 
|  | 177 | Diag(New->getLocation(), diag::err_redefinition_different_kind, | 
|  | 178 | New->getName()); | 
|  | 179 | Diag(OldD->getLocation(), diag::err_previous_definition); | 
|  | 180 | return New; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | // This is not right, but it's a start.  If 'Old' is a function prototype with | 
|  | 184 | // the same type as 'New', silently allow this.  FIXME: We should link up decl | 
|  | 185 | // objects here. | 
|  | 186 | if (Old->getBody() == 0 && | 
|  | 187 | Old->getCanonicalType() == New->getCanonicalType()) { | 
|  | 188 | return New; | 
|  | 189 | } | 
|  | 190 |  | 
|  | 191 | // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. | 
|  | 192 | // TODO: This is totally simplistic.  It should handle merging functions | 
|  | 193 | // together etc, merging extern int X; int X; ... | 
|  | 194 | Diag(New->getLocation(), diag::err_redefinition, New->getName()); | 
|  | 195 | Diag(Old->getLocation(), diag::err_previous_definition); | 
|  | 196 | return New; | 
|  | 197 | } | 
|  | 198 |  | 
|  | 199 | /// MergeVarDecl - We just parsed a variable 'New' which has the same name | 
|  | 200 | /// and scope as a previous declaration 'Old'.  Figure out how to resolve this | 
|  | 201 | /// situation, merging decls or emitting diagnostics as appropriate. | 
|  | 202 | /// | 
|  | 203 | /// FIXME: Need to carefully consider tentative definition rules (C99 6.9.2p2). | 
|  | 204 | /// For example, we incorrectly complain about i1, i4 from C99 6.9.2p4. | 
|  | 205 | /// | 
| Steve Naroff | 8e74c93 | 2007-09-13 21:41:19 +0000 | [diff] [blame] | 206 | VarDecl *Sema::MergeVarDecl(VarDecl *New, ScopedDecl *OldD) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 207 | // Verify the old decl was also a variable. | 
|  | 208 | VarDecl *Old = dyn_cast<VarDecl>(OldD); | 
|  | 209 | if (!Old) { | 
|  | 210 | Diag(New->getLocation(), diag::err_redefinition_different_kind, | 
|  | 211 | New->getName()); | 
|  | 212 | Diag(OldD->getLocation(), diag::err_previous_definition); | 
|  | 213 | return New; | 
|  | 214 | } | 
| Steve Naroff | fb22d96 | 2007-08-30 01:06:46 +0000 | [diff] [blame] | 215 | FileVarDecl *OldFSDecl = dyn_cast<FileVarDecl>(Old); | 
|  | 216 | FileVarDecl *NewFSDecl = dyn_cast<FileVarDecl>(New); | 
|  | 217 | bool OldIsTentative = false; | 
|  | 218 |  | 
|  | 219 | if (OldFSDecl && NewFSDecl) { // C99 6.9.2 | 
|  | 220 | // Handle C "tentative" external object definitions. FIXME: finish! | 
|  | 221 | if (!OldFSDecl->getInit() && | 
|  | 222 | (OldFSDecl->getStorageClass() == VarDecl::None || | 
|  | 223 | OldFSDecl->getStorageClass() == VarDecl::Static)) | 
|  | 224 | OldIsTentative = true; | 
|  | 225 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 226 | // Verify the types match. | 
|  | 227 | if (Old->getCanonicalType() != New->getCanonicalType()) { | 
|  | 228 | Diag(New->getLocation(), diag::err_redefinition, New->getName()); | 
|  | 229 | Diag(Old->getLocation(), diag::err_previous_definition); | 
|  | 230 | return New; | 
|  | 231 | } | 
|  | 232 | // We've verified the types match, now check if Old is "extern". | 
|  | 233 | if (Old->getStorageClass() != VarDecl::Extern) { | 
|  | 234 | Diag(New->getLocation(), diag::err_redefinition, New->getName()); | 
|  | 235 | Diag(Old->getLocation(), diag::err_previous_definition); | 
|  | 236 | } | 
|  | 237 | return New; | 
|  | 238 | } | 
|  | 239 |  | 
|  | 240 | /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with | 
|  | 241 | /// no declarator (e.g. "struct foo;") is parsed. | 
|  | 242 | Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { | 
|  | 243 | // TODO: emit error on 'int;' or 'const enum foo;'. | 
|  | 244 | // TODO: emit error on 'typedef int;' | 
|  | 245 | // if (!DS.isMissingDeclaratorOk()) Diag(...); | 
|  | 246 |  | 
|  | 247 | return 0; | 
|  | 248 | } | 
|  | 249 |  | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 250 | bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) { | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 251 | AssignmentCheckResult result; | 
|  | 252 | SourceLocation loc = Init->getLocStart(); | 
|  | 253 | // Get the type before calling CheckSingleAssignmentConstraints(), since | 
|  | 254 | // it can promote the expression. | 
|  | 255 | QualType rhsType = Init->getType(); | 
|  | 256 |  | 
|  | 257 | result = CheckSingleAssignmentConstraints(DeclType, Init); | 
|  | 258 |  | 
|  | 259 | // decode the result (notice that extensions still return a type). | 
|  | 260 | switch (result) { | 
|  | 261 | case Compatible: | 
|  | 262 | break; | 
|  | 263 | case Incompatible: | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 264 | // FIXME: tighten up this check which should allow: | 
|  | 265 | // char s[] = "abc", which is identical to char s[] = { 'a', 'b', 'c' }; | 
|  | 266 | if (rhsType == Context.getPointerType(Context.CharTy)) | 
|  | 267 | break; | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 268 | Diag(loc, diag::err_typecheck_assign_incompatible, | 
|  | 269 | DeclType.getAsString(), rhsType.getAsString(), | 
|  | 270 | Init->getSourceRange()); | 
|  | 271 | return true; | 
|  | 272 | case PointerFromInt: | 
|  | 273 | // check for null pointer constant (C99 6.3.2.3p3) | 
|  | 274 | if (!Init->isNullPointerConstant(Context)) { | 
|  | 275 | Diag(loc, diag::ext_typecheck_assign_pointer_int, | 
|  | 276 | DeclType.getAsString(), rhsType.getAsString(), | 
|  | 277 | Init->getSourceRange()); | 
|  | 278 | return true; | 
|  | 279 | } | 
|  | 280 | break; | 
|  | 281 | case IntFromPointer: | 
|  | 282 | Diag(loc, diag::ext_typecheck_assign_pointer_int, | 
|  | 283 | DeclType.getAsString(), rhsType.getAsString(), | 
|  | 284 | Init->getSourceRange()); | 
|  | 285 | break; | 
|  | 286 | case IncompatiblePointer: | 
|  | 287 | Diag(loc, diag::ext_typecheck_assign_incompatible_pointer, | 
|  | 288 | DeclType.getAsString(), rhsType.getAsString(), | 
|  | 289 | Init->getSourceRange()); | 
|  | 290 | break; | 
|  | 291 | case CompatiblePointerDiscardsQualifiers: | 
|  | 292 | Diag(loc, diag::ext_typecheck_assign_discards_qualifiers, | 
|  | 293 | DeclType.getAsString(), rhsType.getAsString(), | 
|  | 294 | Init->getSourceRange()); | 
|  | 295 | break; | 
|  | 296 | } | 
|  | 297 | return false; | 
|  | 298 | } | 
|  | 299 |  | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 300 | bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot, | 
|  | 301 | bool isStatic, QualType ElementType) { | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 302 | SourceLocation loc; | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 303 | Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer. | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 304 |  | 
|  | 305 | if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4. | 
|  | 306 | Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange()); | 
|  | 307 | return true; | 
|  | 308 | } else if (CheckSingleInitializer(expr, ElementType)) { | 
|  | 309 | return true; // types weren't compatible. | 
|  | 310 | } | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 311 | if (savExpr != expr) // The type was promoted, update initializer list. | 
|  | 312 | IList->setInit(slot, expr); | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 313 | return false; | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | void Sema::CheckVariableInitList(QualType DeclType, InitListExpr *IList, | 
|  | 317 | QualType ElementType, bool isStatic, | 
|  | 318 | int &nInitializers, bool &hadError) { | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 319 | for (unsigned i = 0; i < IList->getNumInits(); i++) { | 
|  | 320 | Expr *expr = IList->getInit(i); | 
|  | 321 |  | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 322 | if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) { | 
|  | 323 | if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) { | 
| Steve Naroff | 7cf8c44 | 2007-09-04 21:13:33 +0000 | [diff] [blame] | 324 | int maxElements = CAT->getMaximumElements(); | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 325 | CheckConstantInitList(DeclType, InitList, ElementType, isStatic, | 
|  | 326 | maxElements, hadError); | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 327 | } | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 328 | } else { | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 329 | hadError = CheckInitExpr(expr, IList, i, isStatic, ElementType); | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 330 | } | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 331 | nInitializers++; | 
|  | 332 | } | 
|  | 333 | return; | 
|  | 334 | } | 
|  | 335 |  | 
|  | 336 | // FIXME: Doesn't deal with arrays of structures yet. | 
|  | 337 | void Sema::CheckConstantInitList(QualType DeclType, InitListExpr *IList, | 
|  | 338 | QualType ElementType, bool isStatic, | 
|  | 339 | int &totalInits, bool &hadError) { | 
|  | 340 | int maxElementsAtThisLevel = 0; | 
|  | 341 | int nInitsAtLevel = 0; | 
|  | 342 |  | 
|  | 343 | if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) { | 
|  | 344 | // We have a constant array type, compute maxElements *at this level*. | 
| Steve Naroff | 7cf8c44 | 2007-09-04 21:13:33 +0000 | [diff] [blame] | 345 | maxElementsAtThisLevel = CAT->getMaximumElements(); | 
|  | 346 | // Set DeclType, used below to recurse (for multi-dimensional arrays). | 
|  | 347 | DeclType = CAT->getElementType(); | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 348 | } else if (DeclType->isScalarType()) { | 
|  | 349 | Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init, | 
|  | 350 | IList->getSourceRange()); | 
|  | 351 | maxElementsAtThisLevel = 1; | 
|  | 352 | } | 
|  | 353 | // The empty init list "{ }" is treated specially below. | 
|  | 354 | unsigned numInits = IList->getNumInits(); | 
|  | 355 | if (numInits) { | 
|  | 356 | for (unsigned i = 0; i < numInits; i++) { | 
|  | 357 | Expr *expr = IList->getInit(i); | 
|  | 358 |  | 
|  | 359 | if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) { | 
|  | 360 | CheckConstantInitList(DeclType, InitList, ElementType, isStatic, | 
|  | 361 | totalInits, hadError); | 
|  | 362 | } else { | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 363 | hadError = CheckInitExpr(expr, IList, i, isStatic, ElementType); | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 364 | nInitsAtLevel++; // increment the number of initializers at this level. | 
|  | 365 | totalInits--;    // decrement the total number of initializers. | 
|  | 366 |  | 
|  | 367 | // Check if we have space for another initializer. | 
|  | 368 | if ((nInitsAtLevel > maxElementsAtThisLevel) || (totalInits < 0)) | 
|  | 369 | Diag(expr->getLocStart(), diag::warn_excess_initializers, | 
|  | 370 | expr->getSourceRange()); | 
|  | 371 | } | 
|  | 372 | } | 
|  | 373 | if (nInitsAtLevel < maxElementsAtThisLevel) // fill the remaining elements. | 
|  | 374 | totalInits -= (maxElementsAtThisLevel - nInitsAtLevel); | 
|  | 375 | } else { | 
|  | 376 | // we have an initializer list with no elements. | 
|  | 377 | totalInits -= maxElementsAtThisLevel; | 
|  | 378 | if (totalInits < 0) | 
|  | 379 | Diag(IList->getLocStart(), diag::warn_excess_initializers, | 
|  | 380 | IList->getSourceRange()); | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 381 | } | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 382 | return; | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 383 | } | 
|  | 384 |  | 
| Steve Naroff | 9e8925e | 2007-09-04 14:36:54 +0000 | [diff] [blame] | 385 | bool Sema::CheckInitializer(Expr *&Init, QualType &DeclType, bool isStatic) { | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 386 | InitListExpr *InitList = dyn_cast<InitListExpr>(Init); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 387 | if (!InitList) | 
|  | 388 | return CheckSingleInitializer(Init, DeclType); | 
|  | 389 |  | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 390 | // We have an InitListExpr, make sure we set the type. | 
|  | 391 | Init->setType(DeclType); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 392 |  | 
|  | 393 | bool hadError = false; | 
| Steve Naroff | 6f9f307 | 2007-09-02 15:34:30 +0000 | [diff] [blame] | 394 |  | 
| Steve Naroff | 38374b0 | 2007-09-02 20:30:18 +0000 | [diff] [blame] | 395 | // C99 6.7.8p3: The type of the entity to be initialized shall be an array | 
|  | 396 | // of unknown size ("[]") or an object type that is not a variable array type. | 
|  | 397 | if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) { | 
|  | 398 | Expr *expr = VAT->getSizeExpr(); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 399 | if (expr) | 
|  | 400 | return Diag(expr->getLocStart(), diag::err_variable_object_no_init, | 
|  | 401 | expr->getSourceRange()); | 
|  | 402 |  | 
| Steve Naroff | 7cf8c44 | 2007-09-04 21:13:33 +0000 | [diff] [blame] | 403 | // We have a VariableArrayType with unknown size. Note that only the first | 
|  | 404 | // array can have unknown size. For example, "int [][]" is illegal. | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 405 | int numInits = 0; | 
| Steve Naroff | 7cf8c44 | 2007-09-04 21:13:33 +0000 | [diff] [blame] | 406 | CheckVariableInitList(VAT->getElementType(), InitList, VAT->getBaseType(), | 
|  | 407 | isStatic, numInits, hadError); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 408 | if (!hadError) { | 
|  | 409 | // Return a new array type from the number of initializers (C99 6.7.8p22). | 
|  | 410 | llvm::APSInt ConstVal(32); | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 411 | ConstVal = numInits; | 
|  | 412 | DeclType = Context.getConstantArrayType(DeclType, ConstVal, | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 413 | ArrayType::Normal, 0); | 
|  | 414 | } | 
|  | 415 | return hadError; | 
|  | 416 | } | 
|  | 417 | if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) { | 
| Steve Naroff | 7cf8c44 | 2007-09-04 21:13:33 +0000 | [diff] [blame] | 418 | int maxElements = CAT->getMaximumElements(); | 
|  | 419 | CheckConstantInitList(DeclType, InitList, CAT->getBaseType(), | 
|  | 420 | isStatic, maxElements, hadError); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 421 | return hadError; | 
|  | 422 | } | 
| Steve Naroff | 371227d | 2007-09-04 02:20:04 +0000 | [diff] [blame] | 423 | if (DeclType->isScalarType()) { // C99 6.7.8p11: Allow "int x = { 1, 2 };" | 
|  | 424 | int maxElements = 1; | 
|  | 425 | CheckConstantInitList(DeclType, InitList, DeclType, isStatic, maxElements, | 
|  | 426 | hadError); | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 427 | return hadError; | 
| Steve Naroff | 38374b0 | 2007-09-02 20:30:18 +0000 | [diff] [blame] | 428 | } | 
|  | 429 | // FIXME: Handle struct/union types. | 
| Steve Naroff | d35005e | 2007-09-03 01:24:23 +0000 | [diff] [blame] | 430 | return hadError; | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 431 | } | 
|  | 432 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 433 | Sema::DeclTy * | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 434 | Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 435 | ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 436 | IdentifierInfo *II = D.getIdentifier(); | 
|  | 437 |  | 
| Chris Lattner | e80a59c | 2007-07-25 00:24:17 +0000 | [diff] [blame] | 438 | // All of these full declarators require an identifier.  If it doesn't have | 
|  | 439 | // one, the ParsedFreeStandingDeclSpec action should be used. | 
|  | 440 | if (II == 0) { | 
| Chris Lattner | 98e0863 | 2007-08-28 06:17:15 +0000 | [diff] [blame] | 441 | Diag(D.getDeclSpec().getSourceRange().Begin(), | 
|  | 442 | diag::err_declarator_need_ident, | 
| Chris Lattner | e80a59c | 2007-07-25 00:24:17 +0000 | [diff] [blame] | 443 | D.getDeclSpec().getSourceRange(), D.getSourceRange()); | 
|  | 444 | return 0; | 
|  | 445 | } | 
|  | 446 |  | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 447 | // The scope passed in may not be a decl scope.  Zip up the scope tree until | 
|  | 448 | // we find one that is. | 
|  | 449 | while ((S->getFlags() & Scope::DeclScope) == 0) | 
|  | 450 | S = S->getParent(); | 
|  | 451 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 452 | // See if this is a redefinition of a variable in the same scope. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 453 | ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary, | 
|  | 454 | D.getIdentifierLoc(), S); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 455 | if (PrevDecl && !S->isDeclScope(PrevDecl)) | 
|  | 456 | PrevDecl = 0;   // If in outer scope, it isn't the same thing. | 
|  | 457 |  | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 458 | ScopedDecl *New; | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 459 | bool InvalidDecl = false; | 
|  | 460 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 461 | if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { | 
|  | 462 | TypedefDecl *NewTD = ParseTypedefDecl(S, D, LastDeclarator); | 
|  | 463 | if (!NewTD) return 0; | 
|  | 464 |  | 
|  | 465 | // Handle attributes prior to checking for duplicates in MergeVarDecl | 
|  | 466 | HandleDeclAttributes(NewTD, D.getDeclSpec().getAttributes(), | 
|  | 467 | D.getAttributes()); | 
|  | 468 | // Merge the decl with the existing one if appropriate. | 
|  | 469 | if (PrevDecl) { | 
|  | 470 | NewTD = MergeTypeDefDecl(NewTD, PrevDecl); | 
|  | 471 | if (NewTD == 0) return 0; | 
|  | 472 | } | 
|  | 473 | New = NewTD; | 
|  | 474 | if (S->getParent() == 0) { | 
|  | 475 | // C99 6.7.7p2: If a typedef name specifies a variably modified type | 
|  | 476 | // then it shall have block scope. | 
| Steve Naroff | d7444aa | 2007-08-31 17:20:07 +0000 | [diff] [blame] | 477 | if (const VariableArrayType *VAT = | 
|  | 478 | NewTD->getUnderlyingType()->getAsVariablyModifiedType()) { | 
|  | 479 | Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla, | 
|  | 480 | VAT->getSizeExpr()->getSourceRange()); | 
|  | 481 | InvalidDecl = true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 482 | } | 
|  | 483 | } | 
|  | 484 | } else if (D.isFunctionDeclarator()) { | 
|  | 485 | QualType R = GetTypeForDeclarator(D, S); | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 486 | assert(!R.isNull() && "GetTypeForDeclarator() returned null type"); | 
| Steve Naroff | 49b4526 | 2007-07-13 16:58:59 +0000 | [diff] [blame] | 487 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 488 | FunctionDecl::StorageClass SC; | 
|  | 489 | switch (D.getDeclSpec().getStorageClassSpec()) { | 
|  | 490 | default: assert(0 && "Unknown storage class!"); | 
|  | 491 | case DeclSpec::SCS_auto: | 
|  | 492 | case DeclSpec::SCS_register: | 
|  | 493 | Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func, | 
|  | 494 | R.getAsString()); | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 495 | InvalidDecl = true; | 
|  | 496 | break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 497 | case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break; | 
|  | 498 | case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break; | 
|  | 499 | case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break; | 
|  | 500 | } | 
|  | 501 |  | 
|  | 502 | FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC, | 
| Chris Lattner | 70c8b2e | 2007-08-26 04:02:13 +0000 | [diff] [blame] | 503 | D.getDeclSpec().isInlineSpecified(), | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 504 | LastDeclarator); | 
|  | 505 |  | 
|  | 506 | // Merge the decl with the existing one if appropriate. | 
|  | 507 | if (PrevDecl) { | 
|  | 508 | NewFD = MergeFunctionDecl(NewFD, PrevDecl); | 
|  | 509 | if (NewFD == 0) return 0; | 
|  | 510 | } | 
|  | 511 | New = NewFD; | 
|  | 512 | } else { | 
|  | 513 | QualType R = GetTypeForDeclarator(D, S); | 
| Steve Naroff | 53a3234 | 2007-08-28 18:45:29 +0000 | [diff] [blame] | 514 | assert(!R.isNull() && "GetTypeForDeclarator() returned null type"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 515 |  | 
|  | 516 | VarDecl *NewVD; | 
|  | 517 | VarDecl::StorageClass SC; | 
|  | 518 | switch (D.getDeclSpec().getStorageClassSpec()) { | 
|  | 519 | default: assert(0 && "Unknown storage class!"); | 
|  | 520 | case DeclSpec::SCS_unspecified: SC = VarDecl::None; break; | 
|  | 521 | case DeclSpec::SCS_extern:      SC = VarDecl::Extern; break; | 
|  | 522 | case DeclSpec::SCS_static:      SC = VarDecl::Static; break; | 
|  | 523 | case DeclSpec::SCS_auto:        SC = VarDecl::Auto; break; | 
|  | 524 | case DeclSpec::SCS_register:    SC = VarDecl::Register; break; | 
|  | 525 | } | 
|  | 526 | if (S->getParent() == 0) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 527 | // C99 6.9p2: The storage-class specifiers auto and register shall not | 
|  | 528 | // appear in the declaration specifiers in an external declaration. | 
|  | 529 | if (SC == VarDecl::Auto || SC == VarDecl::Register) { | 
|  | 530 | Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope, | 
|  | 531 | R.getAsString()); | 
| Steve Naroff | 53a3234 | 2007-08-28 18:45:29 +0000 | [diff] [blame] | 532 | InvalidDecl = true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 533 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 534 | NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator); | 
| Steve Naroff | f009063 | 2007-09-02 02:04:30 +0000 | [diff] [blame] | 535 | } else { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 536 | NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator); | 
| Steve Naroff | 53a3234 | 2007-08-28 18:45:29 +0000 | [diff] [blame] | 537 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 538 | // Handle attributes prior to checking for duplicates in MergeVarDecl | 
|  | 539 | HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(), | 
|  | 540 | D.getAttributes()); | 
|  | 541 |  | 
|  | 542 | // Merge the decl with the existing one if appropriate. | 
|  | 543 | if (PrevDecl) { | 
|  | 544 | NewVD = MergeVarDecl(NewVD, PrevDecl); | 
|  | 545 | if (NewVD == 0) return 0; | 
|  | 546 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 547 | New = NewVD; | 
|  | 548 | } | 
|  | 549 |  | 
|  | 550 | // If this has an identifier, add it to the scope stack. | 
|  | 551 | if (II) { | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 552 | New->setNext(II->getFETokenInfo<ScopedDecl>()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 553 | II->setFETokenInfo(New); | 
|  | 554 | S->AddDecl(New); | 
|  | 555 | } | 
|  | 556 |  | 
|  | 557 | if (S->getParent() == 0) | 
|  | 558 | AddTopLevelDecl(New, LastDeclarator); | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 559 |  | 
|  | 560 | // If any semantic error occurred, mark the decl as invalid. | 
|  | 561 | if (D.getInvalidType() || InvalidDecl) | 
|  | 562 | New->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 563 |  | 
|  | 564 | return New; | 
|  | 565 | } | 
|  | 566 |  | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 567 | void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) { | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 568 | Decl *RealDecl = static_cast<Decl *>(dcl); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 569 | Expr *Init = static_cast<Expr *>(init); | 
|  | 570 |  | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 571 | assert((RealDecl && Init) && "missing decl or initializer"); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 572 |  | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 573 | VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); | 
|  | 574 | if (!VDecl) { | 
| Steve Naroff | 8e74c93 | 2007-09-13 21:41:19 +0000 | [diff] [blame] | 575 | Diag(dyn_cast<ScopedDecl>(RealDecl)->getLocation(), | 
|  | 576 | diag::err_illegal_initializer); | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 577 | RealDecl->setInvalidDecl(); | 
|  | 578 | return; | 
|  | 579 | } | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 580 | // Get the decls type and save a reference for later, since | 
|  | 581 | // CheckInitializer may change it. | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 582 | QualType DclT = VDecl->getType(), SavT = DclT; | 
|  | 583 | if (BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(VDecl)) { | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 584 | VarDecl::StorageClass SC = BVD->getStorageClass(); | 
|  | 585 | if (SC == VarDecl::Extern) { // C99 6.7.8p5 | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 586 | Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 587 | BVD->setInvalidDecl(); | 
|  | 588 | } else if (!BVD->isInvalidDecl()) { | 
|  | 589 | CheckInitializer(Init, DclT, SC == VarDecl::Static); | 
|  | 590 | } | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 591 | } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(VDecl)) { | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 592 | if (FVD->getStorageClass() == VarDecl::Extern) | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 593 | Diag(VDecl->getLocation(), diag::warn_extern_init); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 594 | if (!FVD->isInvalidDecl()) | 
|  | 595 | CheckInitializer(Init, DclT, true); | 
|  | 596 | } | 
|  | 597 | // If the type changed, it means we had an incomplete type that was | 
|  | 598 | // completed by the initializer. For example: | 
|  | 599 | //   int ary[] = { 1, 3, 5 }; | 
|  | 600 | // "ary" transitions from a VariableArrayType to a ConstantArrayType. | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 601 | if (!VDecl->isInvalidDecl() && (DclT != SavT)) | 
|  | 602 | VDecl->setType(DclT); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 603 |  | 
|  | 604 | // Attach the initializer to the decl. | 
| Steve Naroff | 410e3e2 | 2007-09-12 20:13:48 +0000 | [diff] [blame] | 605 | VDecl->setInit(Init); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 606 | return; | 
|  | 607 | } | 
|  | 608 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 609 | /// The declarators are chained together backwards, reverse the list. | 
|  | 610 | Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) { | 
|  | 611 | // Often we have single declarators, handle them quickly. | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 612 | Decl *GroupDecl = static_cast<Decl*>(group); | 
|  | 613 | if (GroupDecl == 0) | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 614 | return 0; | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 615 |  | 
|  | 616 | ScopedDecl *Group = dyn_cast<ScopedDecl>(GroupDecl); | 
|  | 617 | ScopedDecl *NewGroup = 0; | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 618 | if (Group->getNextDeclarator() == 0) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 619 | NewGroup = Group; | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 620 | else { // reverse the list. | 
|  | 621 | while (Group) { | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 622 | ScopedDecl *Next = Group->getNextDeclarator(); | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 623 | Group->setNextDeclarator(NewGroup); | 
|  | 624 | NewGroup = Group; | 
|  | 625 | Group = Next; | 
|  | 626 | } | 
|  | 627 | } | 
|  | 628 | // Perform semantic analysis that depends on having fully processed both | 
|  | 629 | // the declarator and initializer. | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 630 | for (ScopedDecl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) { | 
| Steve Naroff | bb20469 | 2007-09-12 14:07:44 +0000 | [diff] [blame] | 631 | VarDecl *IDecl = dyn_cast<VarDecl>(ID); | 
|  | 632 | if (!IDecl) | 
|  | 633 | continue; | 
|  | 634 | FileVarDecl *FVD = dyn_cast<FileVarDecl>(IDecl); | 
|  | 635 | BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(IDecl); | 
|  | 636 | QualType T = IDecl->getType(); | 
|  | 637 |  | 
|  | 638 | // C99 6.7.5.2p2: If an identifier is declared to be an object with | 
|  | 639 | // static storage duration, it shall not have a variable length array. | 
|  | 640 | if ((FVD || BVD) && IDecl->getStorageClass() == VarDecl::Static) { | 
|  | 641 | if (const VariableArrayType *VLA = T->getAsVariableArrayType()) { | 
|  | 642 | if (VLA->getSizeExpr()) { | 
|  | 643 | Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla); | 
|  | 644 | IDecl->setInvalidDecl(); | 
|  | 645 | } | 
|  | 646 | } | 
|  | 647 | } | 
|  | 648 | // Block scope. C99 6.7p7: If an identifier for an object is declared with | 
|  | 649 | // no linkage (C99 6.2.2p6), the type for the object shall be complete... | 
|  | 650 | if (BVD && IDecl->getStorageClass() != VarDecl::Extern) { | 
|  | 651 | if (T->isIncompleteType()) { | 
|  | 652 | Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type, | 
|  | 653 | T.getAsString()); | 
|  | 654 | IDecl->setInvalidDecl(); | 
|  | 655 | } | 
|  | 656 | } | 
|  | 657 | // File scope. C99 6.9.2p2: A declaration of an identifier for and | 
|  | 658 | // object that has file scope without an initializer, and without a | 
|  | 659 | // storage-class specifier or with the storage-class specifier "static", | 
|  | 660 | // constitutes a tentative definition. Note: A tentative definition with | 
|  | 661 | // external linkage is valid (C99 6.2.2p5). | 
|  | 662 | if (FVD && !FVD->getInit() && FVD->getStorageClass() == VarDecl::Static) { | 
|  | 663 | // C99 6.9.2p3: If the declaration of an identifier for an object is | 
|  | 664 | // a tentative definition and has internal linkage (C99 6.2.2p3), the | 
|  | 665 | // declared type shall not be an incomplete type. | 
|  | 666 | if (T->isIncompleteType()) { | 
|  | 667 | Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type, | 
|  | 668 | T.getAsString()); | 
|  | 669 | IDecl->setInvalidDecl(); | 
|  | 670 | } | 
|  | 671 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 672 | } | 
|  | 673 | return NewGroup; | 
|  | 674 | } | 
| Steve Naroff | e1223f7 | 2007-08-28 03:03:08 +0000 | [diff] [blame] | 675 |  | 
|  | 676 | // Called from Sema::ParseStartOfFunctionDef(). | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 677 | ParmVarDecl * | 
|  | 678 | Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo, | 
|  | 679 | Scope *FnScope) { | 
|  | 680 | const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo]; | 
|  | 681 |  | 
|  | 682 | IdentifierInfo *II = PI.Ident; | 
|  | 683 | // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. | 
|  | 684 | // Can this happen for params?  We already checked that they don't conflict | 
|  | 685 | // among each other.  Here they can only shadow globals, which is ok. | 
| Chris Lattner | 8b9023b | 2007-07-13 03:05:23 +0000 | [diff] [blame] | 686 | if (/*Decl *PrevDecl = */LookupScopedDecl(II, Decl::IDNS_Ordinary, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 687 | PI.IdentLoc, FnScope)) { | 
|  | 688 |  | 
|  | 689 | } | 
|  | 690 |  | 
|  | 691 | // FIXME: Handle storage class (auto, register). No declarator? | 
|  | 692 | // TODO: Chain to previous parameter with the prevdeclarator chain? | 
| Steve Naroff | 6a9f3e3 | 2007-08-07 22:44:21 +0000 | [diff] [blame] | 693 |  | 
|  | 694 | // Perform the default function/array conversion (C99 6.7.5.3p[7,8]). | 
|  | 695 | // Doing the promotion here has a win and a loss. The win is the type for | 
|  | 696 | // both Decl's and DeclRefExpr's will match (a convenient invariant for the | 
|  | 697 | // code generator). The loss is the orginal type isn't preserved. For example: | 
|  | 698 | // | 
|  | 699 | // void func(int parmvardecl[5]) { // convert "int [5]" to "int *" | 
|  | 700 | //    int blockvardecl[5]; | 
|  | 701 | //    sizeof(parmvardecl);  // size == 4 | 
|  | 702 | //    sizeof(blockvardecl); // size == 20 | 
|  | 703 | // } | 
|  | 704 | // | 
|  | 705 | // For expressions, all implicit conversions are captured using the | 
|  | 706 | // ImplicitCastExpr AST node (we have no such mechanism for Decl's). | 
|  | 707 | // | 
|  | 708 | // FIXME: If a source translation tool needs to see the original type, then | 
|  | 709 | // we need to consider storing both types (in ParmVarDecl)... | 
|  | 710 | // | 
|  | 711 | QualType parmDeclType = QualType::getFromOpaquePtr(PI.TypeInfo); | 
|  | 712 | if (const ArrayType *AT = parmDeclType->getAsArrayType()) | 
|  | 713 | parmDeclType = Context.getPointerType(AT->getElementType()); | 
|  | 714 | else if (parmDeclType->isFunctionType()) | 
|  | 715 | parmDeclType = Context.getPointerType(parmDeclType); | 
|  | 716 |  | 
|  | 717 | ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, parmDeclType, | 
| Steve Naroff | 53a3234 | 2007-08-28 18:45:29 +0000 | [diff] [blame] | 718 | VarDecl::None, 0); | 
|  | 719 | if (PI.InvalidType) | 
|  | 720 | New->setInvalidDecl(); | 
|  | 721 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 722 | // If this has an identifier, add it to the scope stack. | 
|  | 723 | if (II) { | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 724 | New->setNext(II->getFETokenInfo<ScopedDecl>()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 725 | II->setFETokenInfo(New); | 
|  | 726 | FnScope->AddDecl(New); | 
|  | 727 | } | 
|  | 728 |  | 
|  | 729 | return New; | 
|  | 730 | } | 
|  | 731 |  | 
|  | 732 |  | 
|  | 733 | Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { | 
|  | 734 | assert(CurFunctionDecl == 0 && "Function parsing confused"); | 
|  | 735 | assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && | 
|  | 736 | "Not a function declarator!"); | 
|  | 737 | DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; | 
|  | 738 |  | 
|  | 739 | // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' | 
|  | 740 | // for a K&R function. | 
|  | 741 | if (!FTI.hasPrototype) { | 
|  | 742 | for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { | 
|  | 743 | if (FTI.ArgInfo[i].TypeInfo == 0) { | 
|  | 744 | Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared, | 
|  | 745 | FTI.ArgInfo[i].Ident->getName()); | 
|  | 746 | // Implicitly declare the argument as type 'int' for lack of a better | 
|  | 747 | // type. | 
|  | 748 | FTI.ArgInfo[i].TypeInfo = Context.IntTy.getAsOpaquePtr(); | 
|  | 749 | } | 
|  | 750 | } | 
|  | 751 |  | 
|  | 752 | // Since this is a function definition, act as though we have information | 
|  | 753 | // about the arguments. | 
|  | 754 | FTI.hasPrototype = true; | 
|  | 755 | } else { | 
|  | 756 | // FIXME: Diagnose arguments without names in C. | 
|  | 757 |  | 
|  | 758 | } | 
|  | 759 |  | 
|  | 760 | Scope *GlobalScope = FnBodyScope->getParent(); | 
|  | 761 |  | 
|  | 762 | FunctionDecl *FD = | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 763 | static_cast<FunctionDecl*>(ActOnDeclarator(GlobalScope, D, 0)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 764 | CurFunctionDecl = FD; | 
|  | 765 |  | 
|  | 766 | // Create Decl objects for each parameter, adding them to the FunctionDecl. | 
|  | 767 | llvm::SmallVector<ParmVarDecl*, 16> Params; | 
|  | 768 |  | 
|  | 769 | // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes | 
|  | 770 | // no arguments, not a function that takes a single void argument. | 
|  | 771 | if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && | 
|  | 772 | FTI.ArgInfo[0].TypeInfo == Context.VoidTy.getAsOpaquePtr()) { | 
|  | 773 | // empty arg list, don't push any params. | 
|  | 774 | } else { | 
|  | 775 | for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) | 
|  | 776 | Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i,FnBodyScope)); | 
|  | 777 | } | 
|  | 778 |  | 
|  | 779 | FD->setParams(&Params[0], Params.size()); | 
|  | 780 |  | 
|  | 781 | return FD; | 
|  | 782 | } | 
|  | 783 |  | 
|  | 784 | Sema::DeclTy *Sema::ParseFunctionDefBody(DeclTy *D, StmtTy *Body) { | 
|  | 785 | FunctionDecl *FD = static_cast<FunctionDecl*>(D); | 
|  | 786 | FD->setBody((Stmt*)Body); | 
|  | 787 |  | 
|  | 788 | assert(FD == CurFunctionDecl && "Function parsing confused"); | 
|  | 789 | CurFunctionDecl = 0; | 
|  | 790 |  | 
|  | 791 | // Verify and clean out per-function state. | 
|  | 792 |  | 
|  | 793 | // Check goto/label use. | 
|  | 794 | for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator | 
|  | 795 | I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) { | 
|  | 796 | // Verify that we have no forward references left.  If so, there was a goto | 
|  | 797 | // or address of a label taken, but no definition of it.  Label fwd | 
|  | 798 | // definitions are indicated with a null substmt. | 
|  | 799 | if (I->second->getSubStmt() == 0) { | 
|  | 800 | LabelStmt *L = I->second; | 
|  | 801 | // Emit error. | 
|  | 802 | Diag(L->getIdentLoc(), diag::err_undeclared_label_use, L->getName()); | 
|  | 803 |  | 
|  | 804 | // At this point, we have gotos that use the bogus label.  Stitch it into | 
|  | 805 | // the function body so that they aren't leaked and that the AST is well | 
|  | 806 | // formed. | 
|  | 807 | L->setSubStmt(new NullStmt(L->getIdentLoc())); | 
|  | 808 | cast<CompoundStmt>((Stmt*)Body)->push_back(L); | 
|  | 809 | } | 
|  | 810 | } | 
|  | 811 | LabelMap.clear(); | 
|  | 812 |  | 
|  | 813 | return FD; | 
|  | 814 | } | 
|  | 815 |  | 
|  | 816 |  | 
|  | 817 | /// ImplicitlyDefineFunction - An undeclared identifier was used in a function | 
|  | 818 | /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). | 
| Steve Naroff | 8c9f13e | 2007-09-16 16:16:00 +0000 | [diff] [blame] | 819 | ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, | 
|  | 820 | IdentifierInfo &II, Scope *S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 821 | if (getLangOptions().C99)  // Extension in C99. | 
|  | 822 | Diag(Loc, diag::ext_implicit_function_decl, II.getName()); | 
|  | 823 | else  // Legal in C90, but warn about it. | 
|  | 824 | Diag(Loc, diag::warn_implicit_function_decl, II.getName()); | 
|  | 825 |  | 
|  | 826 | // FIXME: handle stuff like: | 
|  | 827 | // void foo() { extern float X(); } | 
|  | 828 | // void bar() { X(); }  <-- implicit decl for X in another scope. | 
|  | 829 |  | 
|  | 830 | // Set a Declarator for the implicit definition: int foo(); | 
|  | 831 | const char *Dummy; | 
|  | 832 | DeclSpec DS; | 
|  | 833 | bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy); | 
|  | 834 | Error = Error; // Silence warning. | 
|  | 835 | assert(!Error && "Error setting up implicit decl!"); | 
|  | 836 | Declarator D(DS, Declarator::BlockContext); | 
|  | 837 | D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, Loc)); | 
|  | 838 | D.SetIdentifier(&II, Loc); | 
|  | 839 |  | 
|  | 840 | // Find translation-unit scope to insert this function into. | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 841 | if (Scope *FnS = S->getFnParent()) | 
|  | 842 | S = FnS->getParent();   // Skip all scopes in a function at once. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 843 | while (S->getParent()) | 
|  | 844 | S = S->getParent(); | 
|  | 845 |  | 
| Steve Naroff | 8c9f13e | 2007-09-16 16:16:00 +0000 | [diff] [blame] | 846 | return dyn_cast<ScopedDecl>(static_cast<Decl*>(ActOnDeclarator(S, D, 0))); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 847 | } | 
|  | 848 |  | 
|  | 849 |  | 
|  | 850 | TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 851 | ScopedDecl *LastDeclarator) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 852 | assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); | 
|  | 853 |  | 
|  | 854 | QualType T = GetTypeForDeclarator(D, S); | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 855 | assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 856 |  | 
|  | 857 | // Scope manipulation handled by caller. | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 858 | TypedefDecl *NewTD = new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), | 
|  | 859 | T, LastDeclarator); | 
|  | 860 | if (D.getInvalidType()) | 
|  | 861 | NewTD->setInvalidDecl(); | 
|  | 862 | return NewTD; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 863 | } | 
|  | 864 |  | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 865 | Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc, | 
|  | 866 | IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
|  | 867 | IdentifierInfo *SuperName, SourceLocation SuperLoc, | 
|  | 868 | IdentifierInfo **ProtocolNames, unsigned NumProtocols, | 
|  | 869 | AttributeList *AttrList) { | 
|  | 870 | assert(ClassName && "Missing class identifier"); | 
|  | 871 | ObjcInterfaceDecl *IDecl; | 
|  | 872 |  | 
|  | 873 | IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, ClassName); | 
|  | 874 |  | 
|  | 875 | // Chain & install the interface decl into the identifier. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 876 | IDecl->setNext(ClassName->getFETokenInfo<ScopedDecl>()); | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 877 | ClassName->setFETokenInfo(IDecl); | 
|  | 878 | return IDecl; | 
|  | 879 | } | 
|  | 880 |  | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 881 | Sema::DeclTy *Sema::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, | 
|  | 882 | IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, | 
|  | 883 | IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { | 
|  | 884 | assert(ProtocolName && "Missing protocol identifier"); | 
|  | 885 | ObjcProtocolDecl *PDecl; | 
|  | 886 |  | 
|  | 887 | PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, ProtocolName); | 
|  | 888 |  | 
|  | 889 | // Chain & install the protocol decl into the identifier. | 
|  | 890 | PDecl->setNext(ProtocolName->getFETokenInfo<ScopedDecl>()); | 
|  | 891 | ProtocolName->setFETokenInfo(PDecl); | 
|  | 892 | return PDecl; | 
|  | 893 | } | 
|  | 894 |  | 
| Fariborz Jahanian | fd225cc | 2007-09-18 20:26:58 +0000 | [diff] [blame] | 895 | Sema::DeclTy *Sema::ObjcStartCatInterface(SourceLocation AtInterfaceLoc, | 
|  | 896 | IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
|  | 897 | IdentifierInfo *CategoryName, SourceLocation CategoryLoc, | 
|  | 898 | IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { | 
|  | 899 | ObjcCategoryDecl *CDecl; | 
|  | 900 | CDecl = new ObjcCategoryDecl(AtInterfaceLoc, ClassName); | 
|  | 901 | assert (ClassName->getFETokenInfo<ScopedDecl>() && "Missing @interface decl"); | 
|  | 902 | Decl *D = static_cast<Decl *>(ClassName->getFETokenInfo<ScopedDecl>()); | 
|  | 903 | assert(isa<ObjcInterfaceDecl>(D) && "Missing @interface decl"); | 
|  | 904 |  | 
|  | 905 | // Chain & install the category decl into the identifier. | 
|  | 906 | // Note that head of the chain is the @interface class type and follow up | 
|  | 907 | // nodes in the chain are the protocol decl nodes. | 
|  | 908 | cast<ObjcInterfaceDecl>(D)->setNext(CDecl); | 
|  | 909 | return CDecl; | 
|  | 910 | } | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 911 | /// ObjcClassDeclaration - | 
|  | 912 | /// Scope will always be top level file scope. | 
|  | 913 | Action::DeclTy * | 
|  | 914 | Sema::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, | 
|  | 915 | IdentifierInfo **IdentList, unsigned NumElts) { | 
|  | 916 | ObjcClassDecl *CDecl = new ObjcClassDecl(AtClassLoc, NumElts); | 
|  | 917 |  | 
|  | 918 | for (unsigned i = 0; i != NumElts; ++i) { | 
|  | 919 | ObjcInterfaceDecl *IDecl; | 
|  | 920 |  | 
| Steve Naroff | 2bd42fa | 2007-09-10 20:51:04 +0000 | [diff] [blame] | 921 | // FIXME: before we create one, look up the interface decl in a hash table. | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 922 | IDecl = new ObjcInterfaceDecl(SourceLocation(), IdentList[i], true); | 
|  | 923 | // Chain & install the interface decl into the identifier. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 924 | IDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>()); | 
| Steve Naroff | 3536b44 | 2007-09-06 21:24:23 +0000 | [diff] [blame] | 925 | IdentList[i]->setFETokenInfo(IDecl); | 
|  | 926 |  | 
|  | 927 | // Remember that this needs to be removed when the scope is popped. | 
|  | 928 | S->AddDecl(IdentList[i]); | 
|  | 929 |  | 
|  | 930 | CDecl->setInterfaceDecl((int)i, IDecl); | 
|  | 931 | } | 
|  | 932 | return CDecl; | 
|  | 933 | } | 
|  | 934 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 935 |  | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 936 | /// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'.  In the | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 937 | /// former case, Name will be non-null.  In the later case, Name will be null. | 
|  | 938 | /// TagType indicates what kind of tag this is. TK indicates whether this is a | 
|  | 939 | /// reference/declaration/definition of a tag. | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 940 | Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 941 | SourceLocation KWLoc, IdentifierInfo *Name, | 
|  | 942 | SourceLocation NameLoc, AttributeList *Attr) { | 
|  | 943 | // If this is a use of an existing tag, it must have a name. | 
|  | 944 | assert((Name != 0 || TK == TK_Definition) && | 
|  | 945 | "Nameless record must be a definition!"); | 
|  | 946 |  | 
|  | 947 | Decl::Kind Kind; | 
|  | 948 | switch (TagType) { | 
|  | 949 | default: assert(0 && "Unknown tag type!"); | 
|  | 950 | case DeclSpec::TST_struct: Kind = Decl::Struct; break; | 
|  | 951 | case DeclSpec::TST_union:  Kind = Decl::Union; break; | 
|  | 952 | //case DeclSpec::TST_class:  Kind = Decl::Class; break; | 
|  | 953 | case DeclSpec::TST_enum:   Kind = Decl::Enum; break; | 
|  | 954 | } | 
|  | 955 |  | 
|  | 956 | // If this is a named struct, check to see if there was a previous forward | 
|  | 957 | // declaration or definition. | 
|  | 958 | if (TagDecl *PrevDecl = | 
|  | 959 | dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag, | 
|  | 960 | NameLoc, S))) { | 
|  | 961 |  | 
|  | 962 | // If this is a use of a previous tag, or if the tag is already declared in | 
|  | 963 | // the same scope (so that the definition/declaration completes or | 
|  | 964 | // rementions the tag), reuse the decl. | 
|  | 965 | if (TK == TK_Reference || S->isDeclScope(PrevDecl)) { | 
|  | 966 | // Make sure that this wasn't declared as an enum and now used as a struct | 
|  | 967 | // or something similar. | 
|  | 968 | if (PrevDecl->getKind() != Kind) { | 
|  | 969 | Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName()); | 
|  | 970 | Diag(PrevDecl->getLocation(), diag::err_previous_use); | 
|  | 971 | } | 
|  | 972 |  | 
|  | 973 | // If this is a use or a forward declaration, we're good. | 
|  | 974 | if (TK != TK_Definition) | 
|  | 975 | return PrevDecl; | 
|  | 976 |  | 
|  | 977 | // Diagnose attempts to redefine a tag. | 
|  | 978 | if (PrevDecl->isDefinition()) { | 
|  | 979 | Diag(NameLoc, diag::err_redefinition, Name->getName()); | 
|  | 980 | Diag(PrevDecl->getLocation(), diag::err_previous_definition); | 
|  | 981 | // If this is a redefinition, recover by making this struct be | 
|  | 982 | // anonymous, which will make any later references get the previous | 
|  | 983 | // definition. | 
|  | 984 | Name = 0; | 
|  | 985 | } else { | 
|  | 986 | // Okay, this is definition of a previously declared or referenced tag. | 
|  | 987 | // Move the location of the decl to be the definition site. | 
|  | 988 | PrevDecl->setLocation(NameLoc); | 
|  | 989 | return PrevDecl; | 
|  | 990 | } | 
|  | 991 | } | 
|  | 992 | // If we get here, this is a definition of a new struct type in a nested | 
|  | 993 | // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new | 
|  | 994 | // type. | 
|  | 995 | } | 
|  | 996 |  | 
|  | 997 | // If there is an identifier, use the location of the identifier as the | 
|  | 998 | // location of the decl, otherwise use the location of the struct/union | 
|  | 999 | // keyword. | 
|  | 1000 | SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; | 
|  | 1001 |  | 
|  | 1002 | // Otherwise, if this is the first time we've seen this tag, create the decl. | 
|  | 1003 | TagDecl *New; | 
|  | 1004 | switch (Kind) { | 
|  | 1005 | default: assert(0 && "Unknown tag kind!"); | 
|  | 1006 | case Decl::Enum: | 
|  | 1007 | // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: | 
|  | 1008 | // enum X { A, B, C } D;    D should chain to X. | 
|  | 1009 | New = new EnumDecl(Loc, Name, 0); | 
|  | 1010 | // If this is an undefined enum, warn. | 
|  | 1011 | if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum); | 
|  | 1012 | break; | 
|  | 1013 | case Decl::Union: | 
|  | 1014 | case Decl::Struct: | 
|  | 1015 | case Decl::Class: | 
|  | 1016 | // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: | 
|  | 1017 | // struct X { int A; } D;    D should chain to X. | 
|  | 1018 | New = new RecordDecl(Kind, Loc, Name, 0); | 
|  | 1019 | break; | 
|  | 1020 | } | 
|  | 1021 |  | 
|  | 1022 | // If this has an identifier, add it to the scope stack. | 
|  | 1023 | if (Name) { | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 1024 | // The scope passed in may not be a decl scope.  Zip up the scope tree until | 
|  | 1025 | // we find one that is. | 
|  | 1026 | while ((S->getFlags() & Scope::DeclScope) == 0) | 
|  | 1027 | S = S->getParent(); | 
|  | 1028 |  | 
|  | 1029 | // Add it to the decl chain. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 1030 | New->setNext(Name->getFETokenInfo<ScopedDecl>()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1031 | Name->setFETokenInfo(New); | 
|  | 1032 | S->AddDecl(New); | 
|  | 1033 | } | 
|  | 1034 |  | 
|  | 1035 | return New; | 
|  | 1036 | } | 
|  | 1037 |  | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1038 | /// ActOnField - Each field of a struct/union/class is passed into this in order | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1039 | /// to create a FieldDecl object for it. | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1040 | Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagDecl, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1041 | SourceLocation DeclStart, | 
|  | 1042 | Declarator &D, ExprTy *BitfieldWidth) { | 
|  | 1043 | IdentifierInfo *II = D.getIdentifier(); | 
|  | 1044 | Expr *BitWidth = (Expr*)BitfieldWidth; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1045 | SourceLocation Loc = DeclStart; | 
|  | 1046 | if (II) Loc = D.getIdentifierLoc(); | 
|  | 1047 |  | 
|  | 1048 | // FIXME: Unnamed fields can be handled in various different ways, for | 
|  | 1049 | // example, unnamed unions inject all members into the struct namespace! | 
|  | 1050 |  | 
|  | 1051 |  | 
|  | 1052 | if (BitWidth) { | 
|  | 1053 | // TODO: Validate. | 
|  | 1054 | //printf("WARNING: BITFIELDS IGNORED!\n"); | 
|  | 1055 |  | 
|  | 1056 | // 6.7.2.1p3 | 
|  | 1057 | // 6.7.2.1p4 | 
|  | 1058 |  | 
|  | 1059 | } else { | 
|  | 1060 | // Not a bitfield. | 
|  | 1061 |  | 
|  | 1062 | // validate II. | 
|  | 1063 |  | 
|  | 1064 | } | 
|  | 1065 |  | 
|  | 1066 | QualType T = GetTypeForDeclarator(D, S); | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 1067 | assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); | 
|  | 1068 | bool InvalidDecl = false; | 
| Steve Naroff | d7444aa | 2007-08-31 17:20:07 +0000 | [diff] [blame] | 1069 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1070 | // C99 6.7.2.1p8: A member of a structure or union may have any type other | 
|  | 1071 | // than a variably modified type. | 
| Steve Naroff | d7444aa | 2007-08-31 17:20:07 +0000 | [diff] [blame] | 1072 | if (const VariableArrayType *VAT = T->getAsVariablyModifiedType()) { | 
|  | 1073 | Diag(Loc, diag::err_typecheck_illegal_vla, | 
|  | 1074 | VAT->getSizeExpr()->getSourceRange()); | 
|  | 1075 | InvalidDecl = true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1076 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1077 | // FIXME: Chain fielddecls together. | 
| Steve Naroff | 4473921 | 2007-09-11 21:17:26 +0000 | [diff] [blame] | 1078 | FieldDecl *NewFD; | 
|  | 1079 |  | 
|  | 1080 | if (isa<RecordDecl>(static_cast<Decl *>(TagDecl))) | 
| Steve Naroff | f38661e | 2007-09-14 02:20:46 +0000 | [diff] [blame] | 1081 | NewFD = new FieldDecl(Loc, II, T); | 
| Steve Naroff | 4473921 | 2007-09-11 21:17:26 +0000 | [diff] [blame] | 1082 | else if (isa<ObjcInterfaceDecl>(static_cast<Decl *>(TagDecl))) | 
| Steve Naroff | f38661e | 2007-09-14 02:20:46 +0000 | [diff] [blame] | 1083 | NewFD = new ObjcIvarDecl(Loc, II, T); | 
| Steve Naroff | 4473921 | 2007-09-11 21:17:26 +0000 | [diff] [blame] | 1084 | else | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1085 | assert(0 && "Sema::ActOnField(): Unknown TagDecl"); | 
| Steve Naroff | 4473921 | 2007-09-11 21:17:26 +0000 | [diff] [blame] | 1086 |  | 
| Steve Naroff | 5912a35 | 2007-08-28 20:14:24 +0000 | [diff] [blame] | 1087 | if (D.getInvalidType() || InvalidDecl) | 
|  | 1088 | NewFD->setInvalidDecl(); | 
|  | 1089 | return NewFD; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1090 | } | 
|  | 1091 |  | 
| Steve Naroff | f13271f | 2007-09-14 23:09:53 +0000 | [diff] [blame] | 1092 | static void ObjcSetIvarVisibility(ObjcIvarDecl *OIvar, | 
|  | 1093 | tok::ObjCKeywordKind ivarVisibility) { | 
|  | 1094 | assert(OIvar && "missing instance variable"); | 
|  | 1095 | switch (ivarVisibility) { | 
|  | 1096 | case tok::objc_private: | 
|  | 1097 | OIvar->setAccessControl(ObjcIvarDecl::Private); | 
|  | 1098 | break; | 
|  | 1099 | case tok::objc_public: | 
|  | 1100 | OIvar->setAccessControl(ObjcIvarDecl::Public); | 
|  | 1101 | break; | 
|  | 1102 | case tok::objc_protected: | 
|  | 1103 | OIvar->setAccessControl(ObjcIvarDecl::Protected); | 
|  | 1104 | break; | 
|  | 1105 | case tok::objc_package: | 
|  | 1106 | OIvar->setAccessControl(ObjcIvarDecl::Package); | 
|  | 1107 | break; | 
|  | 1108 | default: | 
|  | 1109 | OIvar->setAccessControl(ObjcIvarDecl::None); | 
|  | 1110 | break; | 
|  | 1111 | } | 
|  | 1112 | } | 
|  | 1113 |  | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1114 | void Sema::ActOnFields(SourceLocation RecLoc, DeclTy *RecDecl, | 
|  | 1115 | DeclTy **Fields, unsigned NumFields, | 
|  | 1116 | tok::ObjCKeywordKind *visibility) { | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1117 | Decl *EnclosingDecl = static_cast<Decl*>(RecDecl); | 
|  | 1118 | assert(EnclosingDecl && "missing record or interface decl"); | 
|  | 1119 | RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); | 
|  | 1120 |  | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1121 | if (Record && Record->isDefinition()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1122 | // Diagnose code like: | 
|  | 1123 | //     struct S { struct S {} X; }; | 
|  | 1124 | // We discover this when we complete the outer S.  Reject and ignore the | 
|  | 1125 | // outer S. | 
|  | 1126 | Diag(Record->getLocation(), diag::err_nested_redefinition, | 
|  | 1127 | Record->getKindName()); | 
|  | 1128 | Diag(RecLoc, diag::err_previous_definition); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1129 | Record->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1130 | return; | 
|  | 1131 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1132 | // Verify that all the fields are okay. | 
|  | 1133 | unsigned NumNamedMembers = 0; | 
|  | 1134 | llvm::SmallVector<FieldDecl*, 32> RecFields; | 
|  | 1135 | llvm::SmallSet<const IdentifierInfo*, 32> FieldIDs; | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1136 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1137 | for (unsigned i = 0; i != NumFields; ++i) { | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1138 |  | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1139 | FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i])); | 
|  | 1140 | assert(FD && "missing field decl"); | 
|  | 1141 |  | 
|  | 1142 | // Remember all fields. | 
|  | 1143 | RecFields.push_back(FD); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1144 |  | 
|  | 1145 | // Get the type for the field. | 
| Chris Lattner | 02c642e | 2007-07-31 21:33:24 +0000 | [diff] [blame] | 1146 | Type *FDTy = FD->getType().getTypePtr(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1147 |  | 
| Steve Naroff | f13271f | 2007-09-14 23:09:53 +0000 | [diff] [blame] | 1148 | // If we have visibility info, make sure the AST is set accordingly. | 
|  | 1149 | if (visibility) | 
|  | 1150 | ObjcSetIvarVisibility(dyn_cast<ObjcIvarDecl>(FD), visibility[i]); | 
|  | 1151 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1152 | // C99 6.7.2.1p2 - A field may not be a function type. | 
| Chris Lattner | 02c642e | 2007-07-31 21:33:24 +0000 | [diff] [blame] | 1153 | if (FDTy->isFunctionType()) { | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1154 | Diag(FD->getLocation(), diag::err_field_declared_as_function, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1155 | FD->getName()); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1156 | FD->setInvalidDecl(); | 
|  | 1157 | EnclosingDecl->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1158 | continue; | 
|  | 1159 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1160 | // C99 6.7.2.1p2 - A field may not be an incomplete type except... | 
|  | 1161 | if (FDTy->isIncompleteType()) { | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1162 | if (!Record) {  // Incomplete ivar type is always an error. | 
|  | 1163 | Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1164 | FD->setInvalidDecl(); | 
|  | 1165 | EnclosingDecl->setInvalidDecl(); | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1166 | continue; | 
|  | 1167 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1168 | if (i != NumFields-1 ||                   // ... that the last member ... | 
|  | 1169 | Record->getKind() != Decl::Struct ||  // ... of a structure ... | 
| Chris Lattner | 02c642e | 2007-07-31 21:33:24 +0000 | [diff] [blame] | 1170 | !FDTy->isArrayType()) {         //... may have incomplete array type. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1171 | Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1172 | FD->setInvalidDecl(); | 
|  | 1173 | EnclosingDecl->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1174 | continue; | 
|  | 1175 | } | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1176 | if (NumNamedMembers < 1) {  //... must have more than named member ... | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1177 | Diag(FD->getLocation(), diag::err_flexible_array_empty_struct, | 
|  | 1178 | FD->getName()); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1179 | FD->setInvalidDecl(); | 
|  | 1180 | EnclosingDecl->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1181 | continue; | 
|  | 1182 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1183 | // Okay, we have a legal flexible array member at the end of the struct. | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1184 | if (Record) | 
|  | 1185 | Record->setHasFlexibleArrayMember(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1186 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1187 | /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the | 
|  | 1188 | /// field of another structure or the element of an array. | 
| Chris Lattner | 02c642e | 2007-07-31 21:33:24 +0000 | [diff] [blame] | 1189 | if (const RecordType *FDTTy = FDTy->getAsRecordType()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1190 | if (FDTTy->getDecl()->hasFlexibleArrayMember()) { | 
|  | 1191 | // If this is a member of a union, then entire union becomes "flexible". | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1192 | if (Record && Record->getKind() == Decl::Union) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1193 | Record->setHasFlexibleArrayMember(true); | 
|  | 1194 | } else { | 
|  | 1195 | // If this is a struct/class and this is not the last element, reject | 
|  | 1196 | // it.  Note that GCC supports variable sized arrays in the middle of | 
|  | 1197 | // structures. | 
|  | 1198 | if (i != NumFields-1) { | 
|  | 1199 | Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct, | 
|  | 1200 | FD->getName()); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1201 | FD->setInvalidDecl(); | 
|  | 1202 | EnclosingDecl->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1203 | continue; | 
|  | 1204 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1205 | // We support flexible arrays at the end of structs in other structs | 
|  | 1206 | // as an extension. | 
|  | 1207 | Diag(FD->getLocation(), diag::ext_flexible_array_in_struct, | 
|  | 1208 | FD->getName()); | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1209 | if (Record) | 
|  | 1210 | Record->setHasFlexibleArrayMember(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1211 | } | 
|  | 1212 | } | 
|  | 1213 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1214 | // Keep track of the number of named members. | 
|  | 1215 | if (IdentifierInfo *II = FD->getIdentifier()) { | 
|  | 1216 | // Detect duplicate member names. | 
|  | 1217 | if (!FieldIDs.insert(II)) { | 
|  | 1218 | Diag(FD->getLocation(), diag::err_duplicate_member, II->getName()); | 
|  | 1219 | // Find the previous decl. | 
|  | 1220 | SourceLocation PrevLoc; | 
|  | 1221 | for (unsigned i = 0, e = RecFields.size(); ; ++i) { | 
|  | 1222 | assert(i != e && "Didn't find previous def!"); | 
|  | 1223 | if (RecFields[i]->getIdentifier() == II) { | 
|  | 1224 | PrevLoc = RecFields[i]->getLocation(); | 
|  | 1225 | break; | 
|  | 1226 | } | 
|  | 1227 | } | 
|  | 1228 | Diag(PrevLoc, diag::err_previous_definition); | 
| Steve Naroff | 7421664 | 2007-09-14 22:20:54 +0000 | [diff] [blame] | 1229 | FD->setInvalidDecl(); | 
|  | 1230 | EnclosingDecl->setInvalidDecl(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1231 | continue; | 
|  | 1232 | } | 
|  | 1233 | ++NumNamedMembers; | 
|  | 1234 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1235 | } | 
|  | 1236 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1237 | // Okay, we successfully defined 'Record'. | 
| Fariborz Jahanian | e267ab6 | 2007-09-14 16:27:55 +0000 | [diff] [blame] | 1238 | if (Record) | 
|  | 1239 | Record->defineBody(&RecFields[0], RecFields.size()); | 
| Fariborz Jahanian | b04a021 | 2007-09-14 21:08:27 +0000 | [diff] [blame] | 1240 | else { | 
|  | 1241 | ObjcIvarDecl **ClsFields = | 
|  | 1242 | reinterpret_cast<ObjcIvarDecl**>(&RecFields[0]); | 
|  | 1243 | cast<ObjcInterfaceDecl>(static_cast<Decl*>(RecDecl))-> | 
|  | 1244 | ObjcAddInstanceVariablesToClass(ClsFields, RecFields.size()); | 
|  | 1245 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1246 | } | 
|  | 1247 |  | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1248 | void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, | 
|  | 1249 | DeclTy **allMethods, unsigned allNum) { | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1250 | // FIXME: Fix this when we can handle methods declared in protocols. | 
|  | 1251 | // See Parser::ParseObjCAtProtocolDeclaration | 
|  | 1252 | if (!ClassDecl) | 
|  | 1253 | return; | 
| Fariborz Jahanian | e3a2ca7 | 2007-09-10 20:33:04 +0000 | [diff] [blame] | 1254 | llvm::SmallVector<ObjcMethodDecl*, 32> insMethods; | 
|  | 1255 | llvm::SmallVector<ObjcMethodDecl*, 16> clsMethods; | 
|  | 1256 |  | 
|  | 1257 | for (unsigned i = 0; i < allNum; i++ ) { | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1258 | ObjcMethodDecl *Method = | 
| Fariborz Jahanian | e3a2ca7 | 2007-09-10 20:33:04 +0000 | [diff] [blame] | 1259 | cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i])); | 
|  | 1260 | if (!Method) continue;  // Already issued a diagnostic. | 
|  | 1261 | if (Method->isInstance()) | 
|  | 1262 | insMethods.push_back(Method); | 
|  | 1263 | else | 
|  | 1264 | clsMethods.push_back(Method); | 
|  | 1265 | } | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1266 | if (isa<ObjcInterfaceDecl>(static_cast<Decl *>(ClassDecl))) { | 
|  | 1267 | ObjcInterfaceDecl *Interface = cast<ObjcInterfaceDecl>( | 
|  | 1268 | static_cast<Decl*>(ClassDecl)); | 
|  | 1269 | Interface->ObjcAddMethods(&insMethods[0], insMethods.size(), | 
|  | 1270 | &clsMethods[0], clsMethods.size()); | 
|  | 1271 | } | 
|  | 1272 | else if (isa<ObjcProtocolDecl>(static_cast<Decl *>(ClassDecl))) { | 
|  | 1273 | ObjcProtocolDecl *Protocol = cast<ObjcProtocolDecl>( | 
|  | 1274 | static_cast<Decl*>(ClassDecl)); | 
|  | 1275 | Protocol->ObjcAddProtoMethods(&insMethods[0], insMethods.size(), | 
|  | 1276 | &clsMethods[0], clsMethods.size()); | 
|  | 1277 | } | 
| Fariborz Jahanian | fd225cc | 2007-09-18 20:26:58 +0000 | [diff] [blame] | 1278 | else if (isa<ObjcCategoryDecl>(static_cast<Decl *>(ClassDecl))) { | 
|  | 1279 | ObjcCategoryDecl *Category = cast<ObjcCategoryDecl>( | 
|  | 1280 | static_cast<Decl*>(ClassDecl)); | 
|  | 1281 | Category->ObjcAddCatMethods(&insMethods[0], insMethods.size(), | 
|  | 1282 | &clsMethods[0], clsMethods.size()); | 
|  | 1283 | } | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1284 | else | 
|  | 1285 | assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy"); | 
| Fariborz Jahanian | e3a2ca7 | 2007-09-10 20:33:04 +0000 | [diff] [blame] | 1286 | return; | 
|  | 1287 | } | 
|  | 1288 |  | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1289 | Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, | 
| Steve Naroff | 37387c9 | 2007-09-17 20:25:27 +0000 | [diff] [blame] | 1290 | tok::TokenKind MethodType, TypeTy *ReturnType, | 
|  | 1291 | ObjcKeywordDecl *Keywords, unsigned NumKeywords, | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1292 | AttributeList *AttrList, | 
|  | 1293 | tok::ObjCKeywordKind MethodDeclKind) { | 
| Steve Naroff | 37387c9 | 2007-09-17 20:25:27 +0000 | [diff] [blame] | 1294 | assert(NumKeywords && "Selector must be specified"); | 
|  | 1295 |  | 
|  | 1296 | // Derive the selector name from the keyword declarations. | 
| Steve Naroff | 3f128ad | 2007-09-17 14:16:13 +0000 | [diff] [blame] | 1297 | int len=0; | 
| Steve Naroff | 37387c9 | 2007-09-17 20:25:27 +0000 | [diff] [blame] | 1298 | for (unsigned int i = 0; i < NumKeywords; i++) { | 
|  | 1299 | if (Keywords[i].SelectorName) | 
|  | 1300 | len += strlen(Keywords[i].SelectorName->getName()); | 
| Steve Naroff | 3f128ad | 2007-09-17 14:16:13 +0000 | [diff] [blame] | 1301 | len++; | 
|  | 1302 | } | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1303 | llvm::SmallString<128> methodName; | 
| Steve Naroff | 3f128ad | 2007-09-17 14:16:13 +0000 | [diff] [blame] | 1304 | methodName[0] = '\0'; | 
| Steve Naroff | 37387c9 | 2007-09-17 20:25:27 +0000 | [diff] [blame] | 1305 | for (unsigned int i = 0; i < NumKeywords; i++) { | 
|  | 1306 | if (Keywords[i].SelectorName) | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1307 | methodName += Keywords[i].SelectorName->getName(); | 
|  | 1308 | methodName += ":"; | 
| Steve Naroff | 3f128ad | 2007-09-17 14:16:13 +0000 | [diff] [blame] | 1309 | } | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1310 | methodName[len] = '\0'; | 
| Steve Naroff | 21d5a95 | 2007-09-19 16:18:46 +0000 | [diff] [blame^] | 1311 | IdentifierInfo &SelName = Context.Idents.get(&methodName[0], | 
|  | 1312 | &methodName[0]+len); | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1313 | llvm::SmallVector<ParmVarDecl*, 16> Params; | 
|  | 1314 |  | 
|  | 1315 | for (unsigned i = 0; i < NumKeywords; i++) { | 
| Steve Naroff | 37387c9 | 2007-09-17 20:25:27 +0000 | [diff] [blame] | 1316 | ObjcKeywordDecl *arg = &Keywords[i]; | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1317 | // FIXME: arg->AttrList must be stored too! | 
|  | 1318 | ParmVarDecl* Param = new ParmVarDecl(arg->ColonLoc, arg->ArgumentName, | 
|  | 1319 | QualType::getFromOpaquePtr(arg->TypeInfo), | 
|  | 1320 | VarDecl::None, 0); | 
|  | 1321 | // FIXME: 'InvalidType' does not get set by caller yet. | 
|  | 1322 | if (arg->InvalidType) | 
|  | 1323 | Param->setInvalidDecl(); | 
|  | 1324 | Params.push_back(Param); | 
|  | 1325 | } | 
|  | 1326 | QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); | 
| Fariborz Jahanian | 146fbb0 | 2007-09-17 22:36:42 +0000 | [diff] [blame] | 1327 | ObjcMethodDecl* ObjcMethod =  new ObjcMethodDecl(MethodLoc, | 
|  | 1328 | SelName, resultDeclType, | 
|  | 1329 | 0, -1, AttrList, MethodType == tok::minus); | 
|  | 1330 | ObjcMethod->setMethodParams(&Params[0], NumKeywords); | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1331 | if (MethodDeclKind == tok::objc_optional) | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1332 | ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional); | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1333 | else | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1334 | ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required); | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1335 | return ObjcMethod; | 
|  | 1336 | } | 
|  | 1337 |  | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1338 | Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1339 | tok::TokenKind MethodType, TypeTy *ReturnType, | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1340 | IdentifierInfo *SelectorName, AttributeList *AttrList, | 
|  | 1341 | tok::ObjCKeywordKind MethodDeclKind) { | 
| Steve Naroff | 3f128ad | 2007-09-17 14:16:13 +0000 | [diff] [blame] | 1342 | const char *methodName = SelectorName->getName(); | 
| Steve Naroff | 21d5a95 | 2007-09-19 16:18:46 +0000 | [diff] [blame^] | 1343 | IdentifierInfo &SelName = Context.Idents.get(methodName, | 
|  | 1344 | methodName+strlen(methodName)); | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1345 | QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); | 
| Fariborz Jahanian | 146fbb0 | 2007-09-17 22:36:42 +0000 | [diff] [blame] | 1346 | ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, | 
|  | 1347 | SelName, resultDeclType, 0, -1, | 
|  | 1348 | AttrList, MethodType == tok::minus); | 
| Fariborz Jahanian | 0093359 | 2007-09-18 00:25:23 +0000 | [diff] [blame] | 1349 | if (MethodDeclKind == tok::objc_optional) | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1350 | ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional); | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1351 | else | 
| Steve Naroff | 563477d | 2007-09-18 23:55:05 +0000 | [diff] [blame] | 1352 | ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required); | 
| Fariborz Jahanian | 25e077d | 2007-09-17 21:07:36 +0000 | [diff] [blame] | 1353 | return ObjcMethod; | 
| Fariborz Jahanian | e55cd00 | 2007-09-12 18:23:47 +0000 | [diff] [blame] | 1354 | } | 
|  | 1355 |  | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1356 | Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1357 | DeclTy *lastEnumConst, | 
|  | 1358 | SourceLocation IdLoc, IdentifierInfo *Id, | 
|  | 1359 | SourceLocation EqualLoc, ExprTy *val) { | 
|  | 1360 | theEnumDecl = theEnumDecl;  // silence unused warning. | 
|  | 1361 | EnumConstantDecl *LastEnumConst = | 
|  | 1362 | cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst)); | 
|  | 1363 | Expr *Val = static_cast<Expr*>(val); | 
|  | 1364 |  | 
| Chris Lattner | 31e0572 | 2007-08-26 06:24:45 +0000 | [diff] [blame] | 1365 | // The scope passed in may not be a decl scope.  Zip up the scope tree until | 
|  | 1366 | // we find one that is. | 
|  | 1367 | while ((S->getFlags() & Scope::DeclScope) == 0) | 
|  | 1368 | S = S->getParent(); | 
|  | 1369 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1370 | // Verify that there isn't already something declared with this name in this | 
|  | 1371 | // scope. | 
| Steve Naroff | 8e74c93 | 2007-09-13 21:41:19 +0000 | [diff] [blame] | 1372 | if (ScopedDecl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, | 
|  | 1373 | IdLoc, S)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1374 | if (S->isDeclScope(PrevDecl)) { | 
|  | 1375 | if (isa<EnumConstantDecl>(PrevDecl)) | 
|  | 1376 | Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName()); | 
|  | 1377 | else | 
|  | 1378 | Diag(IdLoc, diag::err_redefinition, Id->getName()); | 
|  | 1379 | Diag(PrevDecl->getLocation(), diag::err_previous_definition); | 
|  | 1380 | // FIXME: Don't leak memory: delete Val; | 
|  | 1381 | return 0; | 
|  | 1382 | } | 
|  | 1383 | } | 
|  | 1384 |  | 
|  | 1385 | llvm::APSInt EnumVal(32); | 
|  | 1386 | QualType EltTy; | 
|  | 1387 | if (Val) { | 
| Chris Lattner | 421a23d | 2007-08-27 21:16:18 +0000 | [diff] [blame] | 1388 | // Make sure to promote the operand type to int. | 
|  | 1389 | UsualUnaryConversions(Val); | 
|  | 1390 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1391 | // C99 6.7.2.2p2: Make sure we have an integer constant expression. | 
|  | 1392 | SourceLocation ExpLoc; | 
| Chris Lattner | 590b664 | 2007-07-15 23:26:56 +0000 | [diff] [blame] | 1393 | if (!Val->isIntegerConstantExpr(EnumVal, Context, &ExpLoc)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1394 | Diag(ExpLoc, diag::err_enum_value_not_integer_constant_expr, | 
|  | 1395 | Id->getName()); | 
|  | 1396 | // FIXME: Don't leak memory: delete Val; | 
| Chris Lattner | b7416f9 | 2007-08-27 17:37:24 +0000 | [diff] [blame] | 1397 | Val = 0;  // Just forget about it. | 
| Chris Lattner | e9ca851 | 2007-08-29 16:03:41 +0000 | [diff] [blame] | 1398 | } else { | 
|  | 1399 | EltTy = Val->getType(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1400 | } | 
| Chris Lattner | b7416f9 | 2007-08-27 17:37:24 +0000 | [diff] [blame] | 1401 | } | 
|  | 1402 |  | 
|  | 1403 | if (!Val) { | 
|  | 1404 | if (LastEnumConst) { | 
|  | 1405 | // Assign the last value + 1. | 
|  | 1406 | EnumVal = LastEnumConst->getInitVal(); | 
|  | 1407 | ++EnumVal; | 
| Chris Lattner | 421a23d | 2007-08-27 21:16:18 +0000 | [diff] [blame] | 1408 |  | 
|  | 1409 | // Check for overflow on increment. | 
|  | 1410 | if (EnumVal < LastEnumConst->getInitVal()) | 
|  | 1411 | Diag(IdLoc, diag::warn_enum_value_overflow); | 
|  | 1412 |  | 
| Chris Lattner | b7416f9 | 2007-08-27 17:37:24 +0000 | [diff] [blame] | 1413 | EltTy = LastEnumConst->getType(); | 
|  | 1414 | } else { | 
|  | 1415 | // First value, set to zero. | 
|  | 1416 | EltTy = Context.IntTy; | 
| Chris Lattner | 701e5eb | 2007-09-04 02:45:27 +0000 | [diff] [blame] | 1417 | EnumVal.zextOrTrunc( | 
|  | 1418 | static_cast<uint32_t>(Context.getTypeSize(EltTy, IdLoc))); | 
| Chris Lattner | b7416f9 | 2007-08-27 17:37:24 +0000 | [diff] [blame] | 1419 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1420 | } | 
|  | 1421 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1422 | EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, EltTy, Val, EnumVal, | 
|  | 1423 | LastEnumConst); | 
|  | 1424 |  | 
|  | 1425 | // Register this decl in the current scope stack. | 
| Steve Naroff | c752d04 | 2007-09-13 18:10:37 +0000 | [diff] [blame] | 1426 | New->setNext(Id->getFETokenInfo<ScopedDecl>()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1427 | Id->setFETokenInfo(New); | 
|  | 1428 | S->AddDecl(New); | 
|  | 1429 | return New; | 
|  | 1430 | } | 
|  | 1431 |  | 
| Steve Naroff | 08d92e4 | 2007-09-15 18:49:24 +0000 | [diff] [blame] | 1432 | void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1433 | DeclTy **Elements, unsigned NumElements) { | 
|  | 1434 | EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX)); | 
|  | 1435 | assert(!Enum->isDefinition() && "Enum redefinitions can't reach here"); | 
|  | 1436 |  | 
| Chris Lattner | e37f0be | 2007-08-28 05:10:31 +0000 | [diff] [blame] | 1437 | // TODO: If the result value doesn't fit in an int, it must be a long or long | 
|  | 1438 | // long value.  ISO C does not support this, but GCC does as an extension, | 
|  | 1439 | // emit a warning. | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1440 | unsigned IntWidth = Context.Target.getIntWidth(Enum->getLocation()); | 
| Chris Lattner | e37f0be | 2007-08-28 05:10:31 +0000 | [diff] [blame] | 1441 |  | 
|  | 1442 |  | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1443 | // Verify that all the values are okay, compute the size of the values, and | 
|  | 1444 | // reverse the list. | 
|  | 1445 | unsigned NumNegativeBits = 0; | 
|  | 1446 | unsigned NumPositiveBits = 0; | 
|  | 1447 |  | 
|  | 1448 | // Keep track of whether all elements have type int. | 
|  | 1449 | bool AllElementsInt = true; | 
|  | 1450 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1451 | EnumConstantDecl *EltList = 0; | 
|  | 1452 | for (unsigned i = 0; i != NumElements; ++i) { | 
|  | 1453 | EnumConstantDecl *ECD = | 
|  | 1454 | cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i])); | 
|  | 1455 | if (!ECD) continue;  // Already issued a diagnostic. | 
| Chris Lattner | 211a30e | 2007-08-28 05:27:00 +0000 | [diff] [blame] | 1456 |  | 
|  | 1457 | // If the enum value doesn't fit in an int, emit an extension warning. | 
|  | 1458 | assert(ECD->getInitVal().getBitWidth() >= IntWidth && | 
|  | 1459 | "Should have promoted value to int"); | 
|  | 1460 | const llvm::APSInt &InitVal = ECD->getInitVal(); | 
|  | 1461 | if (InitVal.getBitWidth() > IntWidth) { | 
|  | 1462 | llvm::APSInt V(InitVal); | 
|  | 1463 | V.trunc(IntWidth); | 
|  | 1464 | V.extend(InitVal.getBitWidth()); | 
|  | 1465 | if (V != InitVal) | 
|  | 1466 | Diag(ECD->getLocation(), diag::ext_enum_value_not_int, | 
|  | 1467 | InitVal.toString()); | 
|  | 1468 | } | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1469 |  | 
|  | 1470 | // Keep track of the size of positive and negative values. | 
|  | 1471 | if (InitVal.isUnsigned() || !InitVal.isNegative()) | 
|  | 1472 | NumPositiveBits = std::max(NumPositiveBits, InitVal.getActiveBits()); | 
|  | 1473 | else | 
|  | 1474 | NumNegativeBits = std::max(NumNegativeBits, InitVal.getMinSignedBits()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1475 |  | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1476 | // Keep track of whether every enum element has type int (very commmon). | 
|  | 1477 | if (AllElementsInt) | 
|  | 1478 | AllElementsInt = ECD->getType() == Context.IntTy; | 
|  | 1479 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1480 | ECD->setNextDeclarator(EltList); | 
|  | 1481 | EltList = ECD; | 
|  | 1482 | } | 
|  | 1483 |  | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1484 | // Figure out the type that should be used for this enum. | 
|  | 1485 | // FIXME: Support attribute(packed) on enums and -fshort-enums. | 
|  | 1486 | QualType BestType; | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1487 | unsigned BestWidth; | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1488 |  | 
|  | 1489 | if (NumNegativeBits) { | 
|  | 1490 | // If there is a negative value, figure out the smallest integer type (of | 
|  | 1491 | // int/long/longlong) that fits. | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1492 | if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1493 | BestType = Context.IntTy; | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1494 | BestWidth = IntWidth; | 
|  | 1495 | } else { | 
|  | 1496 | BestWidth = Context.Target.getLongWidth(Enum->getLocation()); | 
|  | 1497 | if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1498 | BestType = Context.LongTy; | 
|  | 1499 | else { | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1500 | BestWidth = Context.Target.getLongLongWidth(Enum->getLocation()); | 
|  | 1501 | if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1502 | Diag(Enum->getLocation(), diag::warn_enum_too_large); | 
|  | 1503 | BestType = Context.LongLongTy; | 
|  | 1504 | } | 
|  | 1505 | } | 
|  | 1506 | } else { | 
|  | 1507 | // If there is no negative value, figure out which of uint, ulong, ulonglong | 
|  | 1508 | // fits. | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1509 | if (NumPositiveBits <= IntWidth) { | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1510 | BestType = Context.UnsignedIntTy; | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1511 | BestWidth = IntWidth; | 
|  | 1512 | } else if (NumPositiveBits <= | 
|  | 1513 | (BestWidth = Context.Target.getLongWidth(Enum->getLocation()))) | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1514 | BestType = Context.UnsignedLongTy; | 
|  | 1515 | else { | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1516 | BestWidth = Context.Target.getLongLongWidth(Enum->getLocation()); | 
|  | 1517 | assert(NumPositiveBits <= BestWidth && | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1518 | "How could an initializer get larger than ULL?"); | 
|  | 1519 | BestType = Context.UnsignedLongLongTy; | 
|  | 1520 | } | 
|  | 1521 | } | 
|  | 1522 |  | 
| Chris Lattner | b7f6e08 | 2007-08-29 17:31:48 +0000 | [diff] [blame] | 1523 | // Loop over all of the enumerator constants, changing their types to match | 
|  | 1524 | // the type of the enum if needed. | 
|  | 1525 | for (unsigned i = 0; i != NumElements; ++i) { | 
|  | 1526 | EnumConstantDecl *ECD = | 
|  | 1527 | cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i])); | 
|  | 1528 | if (!ECD) continue;  // Already issued a diagnostic. | 
|  | 1529 |  | 
|  | 1530 | // Standard C says the enumerators have int type, but we allow, as an | 
|  | 1531 | // extension, the enumerators to be larger than int size.  If each | 
|  | 1532 | // enumerator value fits in an int, type it as an int, otherwise type it the | 
|  | 1533 | // same as the enumerator decl itself.  This means that in "enum { X = 1U }" | 
|  | 1534 | // that X has type 'int', not 'unsigned'. | 
|  | 1535 | if (ECD->getType() == Context.IntTy) | 
|  | 1536 | continue;  // Already int type. | 
|  | 1537 |  | 
|  | 1538 | // Determine whether the value fits into an int. | 
|  | 1539 | llvm::APSInt InitVal = ECD->getInitVal(); | 
|  | 1540 | bool FitsInInt; | 
|  | 1541 | if (InitVal.isUnsigned() || !InitVal.isNegative()) | 
|  | 1542 | FitsInInt = InitVal.getActiveBits() < IntWidth; | 
|  | 1543 | else | 
|  | 1544 | FitsInInt = InitVal.getMinSignedBits() <= IntWidth; | 
|  | 1545 |  | 
|  | 1546 | // If it fits into an integer type, force it.  Otherwise force it to match | 
|  | 1547 | // the enum decl type. | 
|  | 1548 | QualType NewTy; | 
|  | 1549 | unsigned NewWidth; | 
|  | 1550 | bool NewSign; | 
|  | 1551 | if (FitsInInt) { | 
|  | 1552 | NewTy = Context.IntTy; | 
|  | 1553 | NewWidth = IntWidth; | 
|  | 1554 | NewSign = true; | 
|  | 1555 | } else if (ECD->getType() == BestType) { | 
|  | 1556 | // Already the right type! | 
|  | 1557 | continue; | 
|  | 1558 | } else { | 
|  | 1559 | NewTy = BestType; | 
|  | 1560 | NewWidth = BestWidth; | 
|  | 1561 | NewSign = BestType->isSignedIntegerType(); | 
|  | 1562 | } | 
|  | 1563 |  | 
|  | 1564 | // Adjust the APSInt value. | 
|  | 1565 | InitVal.extOrTrunc(NewWidth); | 
|  | 1566 | InitVal.setIsSigned(NewSign); | 
|  | 1567 | ECD->setInitVal(InitVal); | 
|  | 1568 |  | 
|  | 1569 | // Adjust the Expr initializer and type. | 
|  | 1570 | ECD->setInitExpr(new ImplicitCastExpr(NewTy, ECD->getInitExpr())); | 
|  | 1571 | ECD->setType(NewTy); | 
|  | 1572 | } | 
| Chris Lattner | ac60968 | 2007-08-28 06:15:15 +0000 | [diff] [blame] | 1573 |  | 
| Chris Lattner | e00b18c | 2007-08-28 18:24:31 +0000 | [diff] [blame] | 1574 | Enum->defineElements(EltList, BestType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1575 | } | 
|  | 1576 |  | 
|  | 1577 | void Sema::AddTopLevelDecl(Decl *current, Decl *last) { | 
|  | 1578 | if (!current) return; | 
|  | 1579 |  | 
|  | 1580 | // If this is a top-level decl that is chained to some other (e.g. int A,B,C;) | 
|  | 1581 | // remember this in the LastInGroupList list. | 
|  | 1582 | if (last) | 
|  | 1583 | LastInGroupList.push_back((Decl*)last); | 
|  | 1584 | } | 
|  | 1585 |  | 
|  | 1586 | void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) { | 
|  | 1587 | if (strcmp(rawAttr->getAttributeName()->getName(), "vector_size") == 0) { | 
|  | 1588 | if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) { | 
|  | 1589 | QualType newType = HandleVectorTypeAttribute(vDecl->getType(), rawAttr); | 
|  | 1590 | if (!newType.isNull()) // install the new vector type into the decl | 
|  | 1591 | vDecl->setType(newType); | 
|  | 1592 | } | 
|  | 1593 | if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) { | 
|  | 1594 | QualType newType = HandleVectorTypeAttribute(tDecl->getUnderlyingType(), | 
|  | 1595 | rawAttr); | 
|  | 1596 | if (!newType.isNull()) // install the new vector type into the decl | 
|  | 1597 | tDecl->setUnderlyingType(newType); | 
|  | 1598 | } | 
|  | 1599 | } | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1600 | if (strcmp(rawAttr->getAttributeName()->getName(), "ocu_vector_type") == 0) { | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1601 | if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) | 
|  | 1602 | HandleOCUVectorTypeAttribute(tDecl, rawAttr); | 
|  | 1603 | else | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1604 | Diag(rawAttr->getAttributeLoc(), | 
|  | 1605 | diag::err_typecheck_ocu_vector_not_typedef); | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1606 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1607 | // FIXME: add other attributes... | 
|  | 1608 | } | 
|  | 1609 |  | 
|  | 1610 | void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix, | 
|  | 1611 | AttributeList *declarator_postfix) { | 
|  | 1612 | while (declspec_prefix) { | 
|  | 1613 | HandleDeclAttribute(New, declspec_prefix); | 
|  | 1614 | declspec_prefix = declspec_prefix->getNext(); | 
|  | 1615 | } | 
|  | 1616 | while (declarator_postfix) { | 
|  | 1617 | HandleDeclAttribute(New, declarator_postfix); | 
|  | 1618 | declarator_postfix = declarator_postfix->getNext(); | 
|  | 1619 | } | 
|  | 1620 | } | 
|  | 1621 |  | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1622 | void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl, | 
|  | 1623 | AttributeList *rawAttr) { | 
|  | 1624 | QualType curType = tDecl->getUnderlyingType(); | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1625 | // check the attribute arugments. | 
|  | 1626 | if (rawAttr->getNumArgs() != 1) { | 
|  | 1627 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments, | 
|  | 1628 | std::string("1")); | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1629 | return; | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1630 | } | 
|  | 1631 | Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0)); | 
|  | 1632 | llvm::APSInt vecSize(32); | 
|  | 1633 | if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) { | 
|  | 1634 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_vector_size_not_int, | 
|  | 1635 | sizeExpr->getSourceRange()); | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1636 | return; | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1637 | } | 
|  | 1638 | // unlike gcc's vector_size attribute, we do not allow vectors to be defined | 
|  | 1639 | // in conjunction with complex types (pointers, arrays, functions, etc.). | 
|  | 1640 | Type *canonType = curType.getCanonicalType().getTypePtr(); | 
|  | 1641 | if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) { | 
|  | 1642 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_vector_type, | 
|  | 1643 | curType.getCanonicalType().getAsString()); | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1644 | return; | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1645 | } | 
|  | 1646 | // unlike gcc's vector_size attribute, the size is specified as the | 
|  | 1647 | // number of elements, not the number of bytes. | 
| Chris Lattner | 701e5eb | 2007-09-04 02:45:27 +0000 | [diff] [blame] | 1648 | unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1649 |  | 
|  | 1650 | if (vectorSize == 0) { | 
|  | 1651 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_zero_size, | 
|  | 1652 | sizeExpr->getSourceRange()); | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1653 | return; | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1654 | } | 
| Steve Naroff | bea0b34 | 2007-07-29 16:33:31 +0000 | [diff] [blame] | 1655 | // Instantiate/Install the vector type, the number of elements is > 0. | 
|  | 1656 | tDecl->setUnderlyingType(Context.getOCUVectorType(curType, vectorSize)); | 
|  | 1657 | // Remember this typedef decl, we will need it later for diagnostics. | 
|  | 1658 | OCUVectorDecls.push_back(tDecl); | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1659 | } | 
|  | 1660 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1661 | QualType Sema::HandleVectorTypeAttribute(QualType curType, | 
| Chris Lattner | a7674d8 | 2007-07-13 22:13:22 +0000 | [diff] [blame] | 1662 | AttributeList *rawAttr) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1663 | // check the attribute arugments. | 
|  | 1664 | if (rawAttr->getNumArgs() != 1) { | 
|  | 1665 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments, | 
|  | 1666 | std::string("1")); | 
|  | 1667 | return QualType(); | 
|  | 1668 | } | 
|  | 1669 | Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0)); | 
|  | 1670 | llvm::APSInt vecSize(32); | 
| Chris Lattner | 590b664 | 2007-07-15 23:26:56 +0000 | [diff] [blame] | 1671 | if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1672 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_vector_size_not_int, | 
|  | 1673 | sizeExpr->getSourceRange()); | 
|  | 1674 | return QualType(); | 
|  | 1675 | } | 
|  | 1676 | // navigate to the base type - we need to provide for vector pointers, | 
|  | 1677 | // vector arrays, and functions returning vectors. | 
|  | 1678 | Type *canonType = curType.getCanonicalType().getTypePtr(); | 
|  | 1679 |  | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1680 | if (canonType->isPointerType() || canonType->isArrayType() || | 
|  | 1681 | canonType->isFunctionType()) { | 
|  | 1682 | assert(1 && "HandleVector(): Complex type construction unimplemented"); | 
|  | 1683 | /* FIXME: rebuild the type from the inside out, vectorizing the inner type. | 
|  | 1684 | do { | 
|  | 1685 | if (PointerType *PT = dyn_cast<PointerType>(canonType)) | 
|  | 1686 | canonType = PT->getPointeeType().getTypePtr(); | 
|  | 1687 | else if (ArrayType *AT = dyn_cast<ArrayType>(canonType)) | 
|  | 1688 | canonType = AT->getElementType().getTypePtr(); | 
|  | 1689 | else if (FunctionType *FT = dyn_cast<FunctionType>(canonType)) | 
|  | 1690 | canonType = FT->getResultType().getTypePtr(); | 
|  | 1691 | } while (canonType->isPointerType() || canonType->isArrayType() || | 
|  | 1692 | canonType->isFunctionType()); | 
|  | 1693 | */ | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1694 | } | 
|  | 1695 | // the base type must be integer or float. | 
|  | 1696 | if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) { | 
|  | 1697 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_vector_type, | 
|  | 1698 | curType.getCanonicalType().getAsString()); | 
|  | 1699 | return QualType(); | 
|  | 1700 | } | 
| Chris Lattner | 701e5eb | 2007-09-04 02:45:27 +0000 | [diff] [blame] | 1701 | unsigned typeSize = static_cast<unsigned>( | 
|  | 1702 | Context.getTypeSize(curType, rawAttr->getAttributeLoc())); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1703 | // vecSize is specified in bytes - convert to bits. | 
| Chris Lattner | 701e5eb | 2007-09-04 02:45:27 +0000 | [diff] [blame] | 1704 | unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1705 |  | 
|  | 1706 | // the vector size needs to be an integral multiple of the type size. | 
|  | 1707 | if (vectorSize % typeSize) { | 
|  | 1708 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_size, | 
|  | 1709 | sizeExpr->getSourceRange()); | 
|  | 1710 | return QualType(); | 
|  | 1711 | } | 
|  | 1712 | if (vectorSize == 0) { | 
|  | 1713 | Diag(rawAttr->getAttributeLoc(), diag::err_attribute_zero_size, | 
|  | 1714 | sizeExpr->getSourceRange()); | 
|  | 1715 | return QualType(); | 
|  | 1716 | } | 
|  | 1717 | // Since OpenCU requires 3 element vectors (OpenCU 5.1.2), we don't restrict | 
|  | 1718 | // the number of elements to be a power of two (unlike GCC). | 
|  | 1719 | // Instantiate the vector type, the number of elements is > 0. | 
| Steve Naroff | 7332292 | 2007-07-18 18:00:27 +0000 | [diff] [blame] | 1720 | return Context.getVectorType(curType, vectorSize/typeSize); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1721 | } | 
|  | 1722 |  |