| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | //  This file implements semantic analysis for declaration specifiers. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| John McCall | 1951085 | 2010-08-20 18:27:03 +0000 | [diff] [blame] | 14 | #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! | 
|  | 15 | #include "clang/Sema/DeclSpec.h" | 
| Douglas Gregor | 555f57e | 2011-06-25 00:56:27 +0000 | [diff] [blame] | 16 | #include "clang/Sema/LocInfoType.h" | 
| John McCall | 1951085 | 2010-08-20 18:27:03 +0000 | [diff] [blame] | 17 | #include "clang/Sema/ParsedTemplate.h" | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 18 | #include "clang/AST/ASTContext.h" | 
| Douglas Gregor | 555f57e | 2011-06-25 00:56:27 +0000 | [diff] [blame] | 19 | #include "clang/AST/Expr.h" | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 20 | #include "clang/AST/NestedNameSpecifier.h" | 
|  | 21 | #include "clang/AST/TypeLoc.h" | 
| Douglas Gregor | 9b3064b | 2009-04-01 22:41:11 +0000 | [diff] [blame] | 22 | #include "clang/Lex/Preprocessor.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 23 | #include "clang/Basic/LangOptions.h" | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 24 | #include "llvm/ADT/STLExtras.h" | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 25 | #include "llvm/Support/ErrorHandling.h" | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 26 | #include <cstring> | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 27 | using namespace clang; | 
|  | 28 |  | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 29 |  | 
|  | 30 | static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc, | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 31 | unsigned DiagID) { | 
|  | 32 | return D.Report(Loc, DiagID); | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 33 | } | 
|  | 34 |  | 
| Douglas Gregor | 314b97f | 2009-11-10 19:49:08 +0000 | [diff] [blame] | 35 |  | 
|  | 36 | void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { | 
|  | 37 | assert(TemplateId && "NULL template-id annotation?"); | 
|  | 38 | Kind = IK_TemplateId; | 
|  | 39 | this->TemplateId = TemplateId; | 
|  | 40 | StartLocation = TemplateId->TemplateNameLoc; | 
|  | 41 | EndLocation = TemplateId->RAngleLoc; | 
|  | 42 | } | 
|  | 43 |  | 
| Douglas Gregor | 0efc2c1 | 2010-01-13 17:31:36 +0000 | [diff] [blame] | 44 | void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { | 
|  | 45 | assert(TemplateId && "NULL template-id annotation?"); | 
|  | 46 | Kind = IK_ConstructorTemplateId; | 
|  | 47 | this->TemplateId = TemplateId; | 
|  | 48 | StartLocation = TemplateId->TemplateNameLoc; | 
|  | 49 | EndLocation = TemplateId->RAngleLoc; | 
|  | 50 | } | 
|  | 51 |  | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 52 | void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, | 
|  | 53 | TypeLoc TL, SourceLocation ColonColonLoc) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 54 | Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 55 | if (Range.getBegin().isInvalid()) | 
|  | 56 | Range.setBegin(TL.getBeginLoc()); | 
|  | 57 | Range.setEnd(ColonColonLoc); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 58 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 59 | assert(Range == Builder.getSourceRange() && | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 60 | "NestedNameSpecifierLoc range computation incorrect"); | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
|  | 63 | void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, | 
|  | 64 | SourceLocation IdentifierLoc, | 
|  | 65 | SourceLocation ColonColonLoc) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 66 | Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); | 
|  | 67 |  | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 68 | if (Range.getBegin().isInvalid()) | 
|  | 69 | Range.setBegin(IdentifierLoc); | 
|  | 70 | Range.setEnd(ColonColonLoc); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 71 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 72 | assert(Range == Builder.getSourceRange() && | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 73 | "NestedNameSpecifierLoc range computation incorrect"); | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 74 | } | 
|  | 75 |  | 
|  | 76 | void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, | 
|  | 77 | SourceLocation NamespaceLoc, | 
|  | 78 | SourceLocation ColonColonLoc) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 79 | Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); | 
|  | 80 |  | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 81 | if (Range.getBegin().isInvalid()) | 
|  | 82 | Range.setBegin(NamespaceLoc); | 
|  | 83 | Range.setEnd(ColonColonLoc); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 84 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 85 | assert(Range == Builder.getSourceRange() && | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 86 | "NestedNameSpecifierLoc range computation incorrect"); | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 87 | } | 
|  | 88 |  | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 89 | void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, | 
|  | 90 | SourceLocation AliasLoc, | 
|  | 91 | SourceLocation ColonColonLoc) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 92 | Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); | 
|  | 93 |  | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 94 | if (Range.getBegin().isInvalid()) | 
|  | 95 | Range.setBegin(AliasLoc); | 
|  | 96 | Range.setEnd(ColonColonLoc); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 97 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 98 | assert(Range == Builder.getSourceRange() && | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 99 | "NestedNameSpecifierLoc range computation incorrect"); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 100 | } | 
|  | 101 |  | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 102 | void CXXScopeSpec::MakeGlobal(ASTContext &Context, | 
|  | 103 | SourceLocation ColonColonLoc) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 104 | Builder.MakeGlobal(Context, ColonColonLoc); | 
|  | 105 |  | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 106 | Range = SourceRange(ColonColonLoc); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 107 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 108 | assert(Range == Builder.getSourceRange() && | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 109 | "NestedNameSpecifierLoc range computation incorrect"); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | void CXXScopeSpec::MakeTrivial(ASTContext &Context, | 
|  | 113 | NestedNameSpecifier *Qualifier, SourceRange R) { | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 114 | Builder.MakeTrivial(Context, Qualifier, R); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 115 | Range = R; | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 116 | } | 
|  | 117 |  | 
|  | 118 | void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { | 
|  | 119 | if (!Other) { | 
|  | 120 | Range = SourceRange(); | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 121 | Builder.Clear(); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 122 | return; | 
|  | 123 | } | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 124 |  | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 125 | Range = Other.getSourceRange(); | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 126 | Builder.Adopt(Other); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 127 | } | 
|  | 128 |  | 
| John McCall | 9dc71d2 | 2011-07-06 06:57:57 +0000 | [diff] [blame^] | 129 | SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const { | 
|  | 130 | if (!Builder.getRepresentation()) | 
|  | 131 | return SourceLocation(); | 
|  | 132 | return Builder.getTemporary().getLocalBeginLoc(); | 
|  | 133 | } | 
|  | 134 |  | 
| Douglas Gregor | c22b5ff | 2011-02-25 02:25:35 +0000 | [diff] [blame] | 135 | NestedNameSpecifierLoc | 
|  | 136 | CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { | 
| Douglas Gregor | b46ae39 | 2011-03-03 21:48:55 +0000 | [diff] [blame] | 137 | if (!Builder.getRepresentation()) | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 138 | return NestedNameSpecifierLoc(); | 
|  | 139 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 140 | return Builder.getWithLocInContext(Context); | 
| Douglas Gregor | 2e4c34a | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 141 | } | 
|  | 142 |  | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 143 | /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. | 
|  | 144 | /// "TheDeclarator" is the declarator that this will be added to. | 
| John McCall | 0b7e678 | 2011-03-24 11:26:52 +0000 | [diff] [blame] | 145 | DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, | 
| Douglas Gregor | 965acbb | 2009-02-18 07:07:28 +0000 | [diff] [blame] | 146 | SourceLocation EllipsisLoc, | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 147 | ParamInfo *ArgInfo, | 
|  | 148 | unsigned NumArgs, | 
|  | 149 | unsigned TypeQuals, | 
| Douglas Gregor | 83f5172 | 2011-01-26 03:43:54 +0000 | [diff] [blame] | 150 | bool RefQualifierIsLvalueRef, | 
|  | 151 | SourceLocation RefQualifierLoc, | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 152 | ExceptionSpecificationType | 
|  | 153 | ESpecType, | 
|  | 154 | SourceLocation ESpecLoc, | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 155 | ParsedType *Exceptions, | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 156 | SourceRange *ExceptionRanges, | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 157 | unsigned NumExceptions, | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 158 | Expr *NoexceptExpr, | 
| Abramo Bagnara | 796aa44 | 2011-03-12 11:17:06 +0000 | [diff] [blame] | 159 | SourceLocation LocalRangeBegin, | 
|  | 160 | SourceLocation LocalRangeEnd, | 
| Douglas Gregor | dab60ad | 2010-10-01 18:44:50 +0000 | [diff] [blame] | 161 | Declarator &TheDeclarator, | 
|  | 162 | ParsedType TrailingReturnType) { | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 163 | DeclaratorChunk I; | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 164 | I.Kind                        = Function; | 
| Abramo Bagnara | 796aa44 | 2011-03-12 11:17:06 +0000 | [diff] [blame] | 165 | I.Loc                         = LocalRangeBegin; | 
|  | 166 | I.EndLoc                      = LocalRangeEnd; | 
| John McCall | 0b7e678 | 2011-03-24 11:26:52 +0000 | [diff] [blame] | 167 | I.Fun.AttrList                = 0; | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 168 | I.Fun.hasPrototype            = hasProto; | 
|  | 169 | I.Fun.isVariadic              = isVariadic; | 
|  | 170 | I.Fun.EllipsisLoc             = EllipsisLoc.getRawEncoding(); | 
|  | 171 | I.Fun.DeleteArgInfo           = false; | 
|  | 172 | I.Fun.TypeQuals               = TypeQuals; | 
|  | 173 | I.Fun.NumArgs                 = NumArgs; | 
|  | 174 | I.Fun.ArgInfo                 = 0; | 
| Douglas Gregor | 83f5172 | 2011-01-26 03:43:54 +0000 | [diff] [blame] | 175 | I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 176 | I.Fun.RefQualifierLoc         = RefQualifierLoc.getRawEncoding(); | 
|  | 177 | I.Fun.ExceptionSpecType       = ESpecType; | 
|  | 178 | I.Fun.ExceptionSpecLoc        = ESpecLoc.getRawEncoding(); | 
|  | 179 | I.Fun.NumExceptions           = 0; | 
|  | 180 | I.Fun.Exceptions              = 0; | 
|  | 181 | I.Fun.NoexceptExpr            = 0; | 
| Douglas Gregor | dab60ad | 2010-10-01 18:44:50 +0000 | [diff] [blame] | 182 | I.Fun.TrailingReturnType   = TrailingReturnType.getAsOpaquePtr(); | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 183 |  | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 184 | // new[] an argument array if needed. | 
|  | 185 | if (NumArgs) { | 
|  | 186 | // If the 'InlineParams' in Declarator is unused and big enough, put our | 
|  | 187 | // parameter list there (in an effort to avoid new/delete traffic).  If it | 
|  | 188 | // is already used (consider a function returning a function pointer) or too | 
|  | 189 | // small (function taking too many arguments), go to the heap. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 190 | if (!TheDeclarator.InlineParamsUsed && | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 191 | NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) { | 
|  | 192 | I.Fun.ArgInfo = TheDeclarator.InlineParams; | 
|  | 193 | I.Fun.DeleteArgInfo = false; | 
|  | 194 | TheDeclarator.InlineParamsUsed = true; | 
|  | 195 | } else { | 
|  | 196 | I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; | 
|  | 197 | I.Fun.DeleteArgInfo = true; | 
|  | 198 | } | 
|  | 199 | memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); | 
|  | 200 | } | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 201 |  | 
|  | 202 | // Check what exception specification information we should actually store. | 
|  | 203 | switch (ESpecType) { | 
|  | 204 | default: break; // By default, save nothing. | 
|  | 205 | case EST_Dynamic: | 
|  | 206 | // new[] an exception array if needed | 
|  | 207 | if (NumExceptions) { | 
|  | 208 | I.Fun.NumExceptions = NumExceptions; | 
|  | 209 | I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; | 
|  | 210 | for (unsigned i = 0; i != NumExceptions; ++i) { | 
|  | 211 | I.Fun.Exceptions[i].Ty = Exceptions[i]; | 
|  | 212 | I.Fun.Exceptions[i].Range = ExceptionRanges[i]; | 
|  | 213 | } | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 214 | } | 
| Sebastian Redl | 6e5d319 | 2011-03-05 22:42:13 +0000 | [diff] [blame] | 215 | break; | 
|  | 216 |  | 
|  | 217 | case EST_ComputedNoexcept: | 
|  | 218 | I.Fun.NoexceptExpr = NoexceptExpr; | 
|  | 219 | break; | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 220 | } | 
| Chris Lattner | 5af2f35 | 2009-01-20 19:11:22 +0000 | [diff] [blame] | 221 | return I; | 
|  | 222 | } | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 223 |  | 
| Douglas Gregor | 555f57e | 2011-06-25 00:56:27 +0000 | [diff] [blame] | 224 | bool Declarator::isDeclarationOfFunction() const { | 
| Richard Smith | 1ab0d90 | 2011-06-25 02:28:38 +0000 | [diff] [blame] | 225 | for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { | 
|  | 226 | switch (DeclTypeInfo[i].Kind) { | 
|  | 227 | case DeclaratorChunk::Function: | 
|  | 228 | return true; | 
|  | 229 | case DeclaratorChunk::Paren: | 
|  | 230 | continue; | 
|  | 231 | case DeclaratorChunk::Pointer: | 
|  | 232 | case DeclaratorChunk::Reference: | 
|  | 233 | case DeclaratorChunk::Array: | 
|  | 234 | case DeclaratorChunk::BlockPointer: | 
|  | 235 | case DeclaratorChunk::MemberPointer: | 
|  | 236 | return false; | 
|  | 237 | } | 
|  | 238 | llvm_unreachable("Invalid type chunk"); | 
|  | 239 | return false; | 
|  | 240 | } | 
| Douglas Gregor | 555f57e | 2011-06-25 00:56:27 +0000 | [diff] [blame] | 241 |  | 
|  | 242 | switch (DS.getTypeSpecType()) { | 
|  | 243 | case TST_auto: | 
|  | 244 | case TST_bool: | 
|  | 245 | case TST_char: | 
|  | 246 | case TST_char16: | 
|  | 247 | case TST_char32: | 
|  | 248 | case TST_class: | 
|  | 249 | case TST_decimal128: | 
|  | 250 | case TST_decimal32: | 
|  | 251 | case TST_decimal64: | 
|  | 252 | case TST_double: | 
|  | 253 | case TST_enum: | 
|  | 254 | case TST_error: | 
|  | 255 | case TST_float: | 
|  | 256 | case TST_int: | 
|  | 257 | case TST_struct: | 
|  | 258 | case TST_union: | 
|  | 259 | case TST_unknown_anytype: | 
|  | 260 | case TST_unspecified: | 
|  | 261 | case TST_void: | 
|  | 262 | case TST_wchar: | 
|  | 263 | return false; | 
|  | 264 |  | 
|  | 265 | case TST_decltype: | 
|  | 266 | case TST_typeofExpr: | 
|  | 267 | if (Expr *E = DS.getRepAsExpr()) | 
|  | 268 | return E->getType()->isFunctionType(); | 
|  | 269 | return false; | 
|  | 270 |  | 
|  | 271 | case TST_underlyingType: | 
|  | 272 | case TST_typename: | 
|  | 273 | case TST_typeofType: { | 
|  | 274 | QualType QT = DS.getRepAsType().get(); | 
|  | 275 | if (QT.isNull()) | 
|  | 276 | return false; | 
|  | 277 |  | 
|  | 278 | if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) | 
|  | 279 | QT = LIT->getType(); | 
|  | 280 |  | 
|  | 281 | if (QT.isNull()) | 
|  | 282 | return false; | 
|  | 283 |  | 
|  | 284 | return QT->isFunctionType(); | 
|  | 285 | } | 
|  | 286 | } | 
|  | 287 |  | 
|  | 288 | return false; | 
|  | 289 | } | 
|  | 290 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 291 | /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this | 
| Chris Lattner | 2a327d1 | 2009-02-27 18:35:46 +0000 | [diff] [blame] | 292 | /// declaration specifier includes. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 293 | /// | 
|  | 294 | unsigned DeclSpec::getParsedSpecifiers() const { | 
|  | 295 | unsigned Res = 0; | 
|  | 296 | if (StorageClassSpec != SCS_unspecified || | 
|  | 297 | SCS_thread_specified) | 
|  | 298 | Res |= PQ_StorageClassSpecifier; | 
| Mike Stump | d420433 | 2008-06-19 19:52:46 +0000 | [diff] [blame] | 299 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 300 | if (TypeQualifiers != TQ_unspecified) | 
|  | 301 | Res |= PQ_TypeQualifier; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 302 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 303 | if (hasTypeSpecifier()) | 
|  | 304 | Res |= PQ_TypeSpecifier; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 305 |  | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 306 | if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 307 | Res |= PQ_FunctionSpecifier; | 
|  | 308 | return Res; | 
|  | 309 | } | 
|  | 310 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 311 | template <class T> static bool BadSpecifier(T TNew, T TPrev, | 
|  | 312 | const char *&PrevSpec, | 
|  | 313 | unsigned &DiagID) { | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 314 | PrevSpec = DeclSpec::getSpecifierName(TPrev); | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 315 | DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec | 
|  | 316 | : diag::err_invalid_decl_spec_combination); | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 317 | return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 318 | } | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 319 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 320 | const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) { | 
|  | 321 | switch (S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 322 | case DeclSpec::SCS_unspecified: return "unspecified"; | 
|  | 323 | case DeclSpec::SCS_typedef:     return "typedef"; | 
|  | 324 | case DeclSpec::SCS_extern:      return "extern"; | 
|  | 325 | case DeclSpec::SCS_static:      return "static"; | 
|  | 326 | case DeclSpec::SCS_auto:        return "auto"; | 
|  | 327 | case DeclSpec::SCS_register:    return "register"; | 
| Eli Friedman | 63054b3 | 2009-04-19 20:27:55 +0000 | [diff] [blame] | 328 | case DeclSpec::SCS_private_extern: return "__private_extern__"; | 
| Sebastian Redl | 669d5d7 | 2008-11-14 23:42:31 +0000 | [diff] [blame] | 329 | case DeclSpec::SCS_mutable:     return "mutable"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 330 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 331 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 332 | } | 
|  | 333 |  | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 334 | const char *DeclSpec::getSpecifierName(TSW W) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 335 | switch (W) { | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 336 | case TSW_unspecified: return "unspecified"; | 
|  | 337 | case TSW_short:       return "short"; | 
|  | 338 | case TSW_long:        return "long"; | 
|  | 339 | case TSW_longlong:    return "long long"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 340 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 341 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 342 | } | 
|  | 343 |  | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 344 | const char *DeclSpec::getSpecifierName(TSC C) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 345 | switch (C) { | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 346 | case TSC_unspecified: return "unspecified"; | 
|  | 347 | case TSC_imaginary:   return "imaginary"; | 
|  | 348 | case TSC_complex:     return "complex"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 349 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 350 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 351 | } | 
|  | 352 |  | 
|  | 353 |  | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 354 | const char *DeclSpec::getSpecifierName(TSS S) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 355 | switch (S) { | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 356 | case TSS_unspecified: return "unspecified"; | 
|  | 357 | case TSS_signed:      return "signed"; | 
|  | 358 | case TSS_unsigned:    return "unsigned"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 359 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 360 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 361 | } | 
|  | 362 |  | 
|  | 363 | const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { | 
|  | 364 | switch (T) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 365 | case DeclSpec::TST_unspecified: return "unspecified"; | 
|  | 366 | case DeclSpec::TST_void:        return "void"; | 
|  | 367 | case DeclSpec::TST_char:        return "char"; | 
| Argyrios Kyrtzidis | 64c438a | 2008-08-09 16:51:54 +0000 | [diff] [blame] | 368 | case DeclSpec::TST_wchar:       return "wchar_t"; | 
| Alisdair Meredith | f5c209d | 2009-07-14 06:30:34 +0000 | [diff] [blame] | 369 | case DeclSpec::TST_char16:      return "char16_t"; | 
|  | 370 | case DeclSpec::TST_char32:      return "char32_t"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 371 | case DeclSpec::TST_int:         return "int"; | 
|  | 372 | case DeclSpec::TST_float:       return "float"; | 
|  | 373 | case DeclSpec::TST_double:      return "double"; | 
|  | 374 | case DeclSpec::TST_bool:        return "_Bool"; | 
|  | 375 | case DeclSpec::TST_decimal32:   return "_Decimal32"; | 
|  | 376 | case DeclSpec::TST_decimal64:   return "_Decimal64"; | 
|  | 377 | case DeclSpec::TST_decimal128:  return "_Decimal128"; | 
|  | 378 | case DeclSpec::TST_enum:        return "enum"; | 
| Chris Lattner | 99dc914 | 2008-04-13 18:59:07 +0000 | [diff] [blame] | 379 | case DeclSpec::TST_class:       return "class"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 380 | case DeclSpec::TST_union:       return "union"; | 
|  | 381 | case DeclSpec::TST_struct:      return "struct"; | 
| Douglas Gregor | 1a51b4a | 2009-02-09 15:09:02 +0000 | [diff] [blame] | 382 | case DeclSpec::TST_typename:    return "type-name"; | 
| Steve Naroff | d1861fd | 2007-07-31 12:34:36 +0000 | [diff] [blame] | 383 | case DeclSpec::TST_typeofType: | 
|  | 384 | case DeclSpec::TST_typeofExpr:  return "typeof"; | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 385 | case DeclSpec::TST_auto:        return "auto"; | 
|  | 386 | case DeclSpec::TST_decltype:    return "(decltype)"; | 
| Sean Hunt | ca63c20 | 2011-05-24 22:41:36 +0000 | [diff] [blame] | 387 | case DeclSpec::TST_underlyingType: return "__underlying_type"; | 
| John McCall | a5fc472 | 2011-04-09 22:50:59 +0000 | [diff] [blame] | 388 | case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 389 | case DeclSpec::TST_error:       return "(error)"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 390 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 391 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 392 | } | 
|  | 393 |  | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 394 | const char *DeclSpec::getSpecifierName(TQ T) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 395 | switch (T) { | 
| John McCall | 32d335e | 2009-08-03 18:47:27 +0000 | [diff] [blame] | 396 | case DeclSpec::TQ_unspecified: return "unspecified"; | 
|  | 397 | case DeclSpec::TQ_const:       return "const"; | 
|  | 398 | case DeclSpec::TQ_restrict:    return "restrict"; | 
|  | 399 | case DeclSpec::TQ_volatile:    return "volatile"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 400 | } | 
| Jeffrey Yasskin | 9f61aa9 | 2009-12-12 05:05:38 +0000 | [diff] [blame] | 401 | llvm_unreachable("Unknown typespec!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 402 | } | 
|  | 403 |  | 
|  | 404 | bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 405 | const char *&PrevSpec, | 
| Peter Collingbourne | e2f82f7 | 2011-02-11 19:59:54 +0000 | [diff] [blame] | 406 | unsigned &DiagID, | 
|  | 407 | const LangOptions &Lang) { | 
|  | 408 | // OpenCL prohibits extern, auto, register, and static | 
|  | 409 | // It seems sensible to prohibit private_extern too | 
|  | 410 | if (Lang.OpenCL) { | 
|  | 411 | switch (S) { | 
|  | 412 | case SCS_extern: | 
|  | 413 | case SCS_private_extern: | 
|  | 414 | case SCS_auto: | 
|  | 415 | case SCS_register: | 
|  | 416 | case SCS_static: | 
|  | 417 | DiagID   = diag::err_not_opencl_storage_class_specifier; | 
|  | 418 | PrevSpec = getSpecifierName(S); | 
|  | 419 | return true; | 
|  | 420 | default: | 
|  | 421 | break; | 
|  | 422 | } | 
|  | 423 | } | 
|  | 424 |  | 
| Abramo Bagnara | 35f9a19 | 2010-07-30 16:47:02 +0000 | [diff] [blame] | 425 | if (StorageClassSpec != SCS_unspecified) { | 
|  | 426 | // Changing storage class is allowed only if the previous one | 
|  | 427 | // was the 'extern' that is part of a linkage specification and | 
|  | 428 | // the new storage class is 'typedef'. | 
|  | 429 | if (!(SCS_extern_in_linkage_spec && | 
|  | 430 | StorageClassSpec == SCS_extern && | 
|  | 431 | S == SCS_typedef)) | 
|  | 432 | return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID); | 
|  | 433 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 434 | StorageClassSpec = S; | 
|  | 435 | StorageClassSpecLoc = Loc; | 
| Sebastian Redl | 669d5d7 | 2008-11-14 23:42:31 +0000 | [diff] [blame] | 436 | assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 437 | return false; | 
|  | 438 | } | 
|  | 439 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 440 | bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 441 | const char *&PrevSpec, | 
|  | 442 | unsigned &DiagID) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 443 | if (SCS_thread_specified) { | 
|  | 444 | PrevSpec = "__thread"; | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 445 | DiagID = diag::ext_duplicate_declspec; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 446 | return true; | 
|  | 447 | } | 
|  | 448 | SCS_thread_specified = true; | 
|  | 449 | SCS_threadLoc = Loc; | 
|  | 450 | return false; | 
|  | 451 | } | 
|  | 452 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 453 | /// These methods set the specified attribute of the DeclSpec, but return true | 
|  | 454 | /// and ignore the request if invalid (e.g. "extern" then "auto" is | 
|  | 455 | /// specified). | 
|  | 456 | bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 457 | const char *&PrevSpec, | 
|  | 458 | unsigned &DiagID) { | 
| Abramo Bagnara | 2553eaf | 2011-03-06 22:21:56 +0000 | [diff] [blame] | 459 | // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that | 
|  | 460 | // for 'long long' we will keep the source location of the first 'long'. | 
|  | 461 | if (TypeSpecWidth == TSW_unspecified) | 
|  | 462 | TSWLoc = Loc; | 
|  | 463 | // Allow turning long -> long long. | 
|  | 464 | else if (W != TSW_longlong || TypeSpecWidth != TSW_long) | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 465 | return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 466 | TypeSpecWidth = W; | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 467 | if (TypeAltiVecVector && !TypeAltiVecBool && | 
|  | 468 | ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { | 
| John Thompson | 82287d1 | 2010-02-05 00:12:22 +0000 | [diff] [blame] | 469 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 470 | DiagID = diag::warn_vector_long_decl_spec_combination; | 
|  | 471 | return true; | 
|  | 472 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 473 | return false; | 
|  | 474 | } | 
|  | 475 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 476 | bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 477 | const char *&PrevSpec, | 
|  | 478 | unsigned &DiagID) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 479 | if (TypeSpecComplex != TSC_unspecified) | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 480 | return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 481 | TypeSpecComplex = C; | 
|  | 482 | TSCLoc = Loc; | 
|  | 483 | return false; | 
|  | 484 | } | 
|  | 485 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 486 | bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 487 | const char *&PrevSpec, | 
|  | 488 | unsigned &DiagID) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 489 | if (TypeSpecSign != TSS_unspecified) | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 490 | return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 491 | TypeSpecSign = S; | 
|  | 492 | TSSLoc = Loc; | 
|  | 493 | return false; | 
|  | 494 | } | 
|  | 495 |  | 
|  | 496 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 497 | const char *&PrevSpec, | 
|  | 498 | unsigned &DiagID, | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 499 | ParsedType Rep) { | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 500 | return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep); | 
|  | 501 | } | 
|  | 502 |  | 
|  | 503 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, | 
|  | 504 | SourceLocation TagNameLoc, | 
|  | 505 | const char *&PrevSpec, | 
|  | 506 | unsigned &DiagID, | 
|  | 507 | ParsedType Rep) { | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 508 | assert(isTypeRep(T) && "T does not store a type"); | 
|  | 509 | assert(Rep && "no type provided!"); | 
|  | 510 | if (TypeSpecType != TST_unspecified) { | 
|  | 511 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 512 | DiagID = diag::err_invalid_decl_spec_combination; | 
|  | 513 | return true; | 
|  | 514 | } | 
|  | 515 | TypeSpecType = T; | 
|  | 516 | TypeRep = Rep; | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 517 | TSTLoc = TagKwLoc; | 
|  | 518 | TSTNameLoc = TagNameLoc; | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 519 | TypeSpecOwned = false; | 
|  | 520 | return false; | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, | 
|  | 524 | const char *&PrevSpec, | 
|  | 525 | unsigned &DiagID, | 
|  | 526 | Expr *Rep) { | 
|  | 527 | assert(isExprRep(T) && "T does not store an expr"); | 
|  | 528 | assert(Rep && "no expression provided!"); | 
|  | 529 | if (TypeSpecType != TST_unspecified) { | 
|  | 530 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 531 | DiagID = diag::err_invalid_decl_spec_combination; | 
|  | 532 | return true; | 
|  | 533 | } | 
|  | 534 | TypeSpecType = T; | 
|  | 535 | ExprRep = Rep; | 
|  | 536 | TSTLoc = Loc; | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 537 | TSTNameLoc = Loc; | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 538 | TypeSpecOwned = false; | 
|  | 539 | return false; | 
|  | 540 | } | 
|  | 541 |  | 
|  | 542 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, | 
|  | 543 | const char *&PrevSpec, | 
|  | 544 | unsigned &DiagID, | 
|  | 545 | Decl *Rep, bool Owned) { | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 546 | return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned); | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, | 
|  | 550 | SourceLocation TagNameLoc, | 
|  | 551 | const char *&PrevSpec, | 
|  | 552 | unsigned &DiagID, | 
|  | 553 | Decl *Rep, bool Owned) { | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 554 | assert(isDeclRep(T) && "T does not store a decl"); | 
|  | 555 | // Unlike the other cases, we don't assert that we actually get a decl. | 
|  | 556 |  | 
|  | 557 | if (TypeSpecType != TST_unspecified) { | 
|  | 558 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 559 | DiagID = diag::err_invalid_decl_spec_combination; | 
|  | 560 | return true; | 
|  | 561 | } | 
|  | 562 | TypeSpecType = T; | 
|  | 563 | DeclRep = Rep; | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 564 | TSTLoc = TagKwLoc; | 
|  | 565 | TSTNameLoc = TagNameLoc; | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 566 | TypeSpecOwned = Owned; | 
|  | 567 | return false; | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, | 
|  | 571 | const char *&PrevSpec, | 
|  | 572 | unsigned &DiagID) { | 
|  | 573 | assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && | 
|  | 574 | "rep required for these type-spec kinds!"); | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 575 | if (TypeSpecType != TST_unspecified) { | 
|  | 576 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 577 | DiagID = diag::err_invalid_decl_spec_combination; | 
|  | 578 | return true; | 
|  | 579 | } | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 580 | TSTLoc = Loc; | 
|  | 581 | TSTNameLoc = Loc; | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 582 | if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { | 
|  | 583 | TypeAltiVecBool = true; | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 584 | return false; | 
|  | 585 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 586 | TypeSpecType = T; | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 587 | TypeSpecOwned = false; | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 588 | if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) { | 
| John Thompson | 82287d1 | 2010-02-05 00:12:22 +0000 | [diff] [blame] | 589 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 590 | DiagID = diag::err_invalid_vector_decl_spec; | 
| John Thompson | 82287d1 | 2010-02-05 00:12:22 +0000 | [diff] [blame] | 591 | return true; | 
|  | 592 | } | 
|  | 593 | return false; | 
|  | 594 | } | 
|  | 595 |  | 
|  | 596 | bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, | 
|  | 597 | const char *&PrevSpec, unsigned &DiagID) { | 
|  | 598 | if (TypeSpecType != TST_unspecified) { | 
|  | 599 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 600 | DiagID = diag::err_invalid_vector_decl_spec_combination; | 
|  | 601 | return true; | 
|  | 602 | } | 
|  | 603 | TypeAltiVecVector = isAltiVecVector; | 
|  | 604 | AltiVecLoc = Loc; | 
|  | 605 | return false; | 
|  | 606 | } | 
|  | 607 |  | 
|  | 608 | bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, | 
|  | 609 | const char *&PrevSpec, unsigned &DiagID) { | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 610 | if (!TypeAltiVecVector || TypeAltiVecPixel || | 
|  | 611 | (TypeSpecType != TST_unspecified)) { | 
| John Thompson | 82287d1 | 2010-02-05 00:12:22 +0000 | [diff] [blame] | 612 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); | 
|  | 613 | DiagID = diag::err_invalid_pixel_decl_spec_combination; | 
|  | 614 | return true; | 
|  | 615 | } | 
| John Thompson | 82287d1 | 2010-02-05 00:12:22 +0000 | [diff] [blame] | 616 | TypeAltiVecPixel = isAltiVecPixel; | 
|  | 617 | TSTLoc = Loc; | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 618 | TSTNameLoc = Loc; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 619 | return false; | 
|  | 620 | } | 
|  | 621 |  | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 622 | bool DeclSpec::SetTypeSpecError() { | 
|  | 623 | TypeSpecType = TST_error; | 
| John McCall | 9e46b8c | 2010-08-26 17:22:34 +0000 | [diff] [blame] | 624 | TypeSpecOwned = false; | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 625 | TSTLoc = SourceLocation(); | 
| Abramo Bagnara | 0daaf32 | 2011-03-16 20:16:18 +0000 | [diff] [blame] | 626 | TSTNameLoc = SourceLocation(); | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 627 | return false; | 
|  | 628 | } | 
|  | 629 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 630 | bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 631 | unsigned &DiagID, const LangOptions &Lang) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 632 | // Duplicates turn into warnings pre-C99. | 
|  | 633 | if ((TypeQualifiers & T) && !Lang.C99) | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 634 | return BadSpecifier(T, T, PrevSpec, DiagID); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 635 | TypeQualifiers |= T; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 636 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 637 | switch (T) { | 
|  | 638 | default: assert(0 && "Unknown type qualifier!"); | 
|  | 639 | case TQ_const:    TQ_constLoc = Loc; break; | 
|  | 640 | case TQ_restrict: TQ_restrictLoc = Loc; break; | 
|  | 641 | case TQ_volatile: TQ_volatileLoc = Loc; break; | 
|  | 642 | } | 
|  | 643 | return false; | 
|  | 644 | } | 
|  | 645 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 646 | bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, | 
|  | 647 | unsigned &DiagID) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 648 | // 'inline inline' is ok. | 
|  | 649 | FS_inline_specified = true; | 
|  | 650 | FS_inlineLoc = Loc; | 
|  | 651 | return false; | 
|  | 652 | } | 
|  | 653 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 654 | bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, | 
|  | 655 | unsigned &DiagID) { | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 656 | // 'virtual virtual' is ok. | 
|  | 657 | FS_virtual_specified = true; | 
|  | 658 | FS_virtualLoc = Loc; | 
|  | 659 | return false; | 
|  | 660 | } | 
|  | 661 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 662 | bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, | 
|  | 663 | unsigned &DiagID) { | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 664 | // 'explicit explicit' is ok. | 
|  | 665 | FS_explicit_specified = true; | 
|  | 666 | FS_explicitLoc = Loc; | 
|  | 667 | return false; | 
|  | 668 | } | 
|  | 669 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 670 | bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, | 
|  | 671 | unsigned &DiagID) { | 
| Anders Carlsson | f47f7a1 | 2009-05-06 04:46:28 +0000 | [diff] [blame] | 672 | if (Friend_specified) { | 
|  | 673 | PrevSpec = "friend"; | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 674 | DiagID = diag::ext_duplicate_declspec; | 
| Anders Carlsson | f47f7a1 | 2009-05-06 04:46:28 +0000 | [diff] [blame] | 675 | return true; | 
|  | 676 | } | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 677 |  | 
| Anders Carlsson | f47f7a1 | 2009-05-06 04:46:28 +0000 | [diff] [blame] | 678 | Friend_specified = true; | 
|  | 679 | FriendLoc = Loc; | 
|  | 680 | return false; | 
|  | 681 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 682 |  | 
| Sebastian Redl | 2ac6723 | 2009-11-05 15:47:02 +0000 | [diff] [blame] | 683 | bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, | 
|  | 684 | unsigned &DiagID) { | 
|  | 685 | // 'constexpr constexpr' is ok. | 
|  | 686 | Constexpr_specified = true; | 
|  | 687 | ConstexprLoc = Loc; | 
|  | 688 | return false; | 
|  | 689 | } | 
|  | 690 |  | 
| John McCall | d226f65 | 2010-08-21 09:40:31 +0000 | [diff] [blame] | 691 | void DeclSpec::setProtocolQualifiers(Decl * const *Protos, | 
| Argyrios Kyrtzidis | e3a535b | 2009-09-29 19:42:11 +0000 | [diff] [blame] | 692 | unsigned NP, | 
|  | 693 | SourceLocation *ProtoLocs, | 
|  | 694 | SourceLocation LAngleLoc) { | 
|  | 695 | if (NP == 0) return; | 
| John McCall | d226f65 | 2010-08-21 09:40:31 +0000 | [diff] [blame] | 696 | ProtocolQualifiers = new Decl*[NP]; | 
| Argyrios Kyrtzidis | e3a535b | 2009-09-29 19:42:11 +0000 | [diff] [blame] | 697 | ProtocolLocs = new SourceLocation[NP]; | 
| John McCall | d226f65 | 2010-08-21 09:40:31 +0000 | [diff] [blame] | 698 | memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP); | 
| Argyrios Kyrtzidis | e3a535b | 2009-09-29 19:42:11 +0000 | [diff] [blame] | 699 | memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP); | 
|  | 700 | NumProtocolQualifiers = NP; | 
|  | 701 | ProtocolLAngleLoc = LAngleLoc; | 
|  | 702 | } | 
|  | 703 |  | 
| Douglas Gregor | ddf889a | 2010-01-18 18:04:31 +0000 | [diff] [blame] | 704 | void DeclSpec::SaveWrittenBuiltinSpecs() { | 
|  | 705 | writtenBS.Sign = getTypeSpecSign(); | 
|  | 706 | writtenBS.Width = getTypeSpecWidth(); | 
|  | 707 | writtenBS.Type = getTypeSpecType(); | 
|  | 708 | // Search the list of attributes for the presence of a mode attribute. | 
|  | 709 | writtenBS.ModeAttr = false; | 
| John McCall | 7f040a9 | 2010-12-24 02:08:15 +0000 | [diff] [blame] | 710 | AttributeList* attrs = getAttributes().getList(); | 
| Douglas Gregor | ddf889a | 2010-01-18 18:04:31 +0000 | [diff] [blame] | 711 | while (attrs) { | 
|  | 712 | if (attrs->getKind() == AttributeList::AT_mode) { | 
|  | 713 | writtenBS.ModeAttr = true; | 
|  | 714 | break; | 
|  | 715 | } | 
|  | 716 | attrs = attrs->getNext(); | 
|  | 717 | } | 
|  | 718 | } | 
|  | 719 |  | 
| Abramo Bagnara | 35f9a19 | 2010-07-30 16:47:02 +0000 | [diff] [blame] | 720 | void DeclSpec::SaveStorageSpecifierAsWritten() { | 
|  | 721 | if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern) | 
|  | 722 | // If 'extern' is part of a linkage specification, | 
|  | 723 | // then it is not a storage class "as written". | 
|  | 724 | StorageClassSpecAsWritten = SCS_unspecified; | 
|  | 725 | else | 
|  | 726 | StorageClassSpecAsWritten = StorageClassSpec; | 
|  | 727 | } | 
|  | 728 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 729 | /// Finish - This does final analysis of the declspec, rejecting things like | 
|  | 730 | /// "_Imaginary" (lacking an FP type).  This returns a diagnostic to issue or | 
|  | 731 | /// diag::NUM_DIAGNOSTICS if there is no error.  After calling this method, | 
|  | 732 | /// DeclSpec is guaranteed self-consistent, even if an error occurred. | 
| Douglas Gregor | 9b3064b | 2009-04-01 22:41:11 +0000 | [diff] [blame] | 733 | void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) { | 
| Douglas Gregor | ddf889a | 2010-01-18 18:04:31 +0000 | [diff] [blame] | 734 | // Before possibly changing their values, save specs as written. | 
|  | 735 | SaveWrittenBuiltinSpecs(); | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 736 | SaveStorageSpecifierAsWritten(); | 
| Douglas Gregor | ddf889a | 2010-01-18 18:04:31 +0000 | [diff] [blame] | 737 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 738 | // Check the type specifier components first. | 
|  | 739 |  | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 740 | // Validate and finalize AltiVec vector declspec. | 
|  | 741 | if (TypeAltiVecVector) { | 
|  | 742 | if (TypeAltiVecBool) { | 
|  | 743 | // Sign specifiers are not allowed with vector bool. (PIM 2.1) | 
|  | 744 | if (TypeSpecSign != TSS_unspecified) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 745 | Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec) | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 746 | << getSpecifierName((TSS)TypeSpecSign); | 
|  | 747 | } | 
|  | 748 |  | 
|  | 749 | // Only char/int are valid with vector bool. (PIM 2.1) | 
| Duncan Sands | 2e964a92 | 2010-06-23 19:34:52 +0000 | [diff] [blame] | 750 | if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) && | 
|  | 751 | (TypeSpecType != TST_int)) || TypeAltiVecPixel) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 752 | Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec) | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 753 | << (TypeAltiVecPixel ? "__pixel" : | 
|  | 754 | getSpecifierName((TST)TypeSpecType)); | 
|  | 755 | } | 
|  | 756 |  | 
|  | 757 | // Only 'short' is valid with vector bool. (PIM 2.1) | 
|  | 758 | if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short)) | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 759 | Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec) | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 760 | << getSpecifierName((TSW)TypeSpecWidth); | 
|  | 761 |  | 
|  | 762 | // Elements of vector bool are interpreted as unsigned. (PIM 2.1) | 
|  | 763 | if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || | 
|  | 764 | (TypeSpecWidth != TSW_unspecified)) | 
|  | 765 | TypeSpecSign = TSS_unsigned; | 
|  | 766 | } | 
|  | 767 |  | 
|  | 768 | if (TypeAltiVecPixel) { | 
|  | 769 | //TODO: perform validation | 
|  | 770 | TypeSpecType = TST_int; | 
|  | 771 | TypeSpecSign = TSS_unsigned; | 
|  | 772 | TypeSpecWidth = TSW_short; | 
| John McCall | 9e46b8c | 2010-08-26 17:22:34 +0000 | [diff] [blame] | 773 | TypeSpecOwned = false; | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 774 | } | 
|  | 775 | } | 
|  | 776 |  | 
| Argyrios Kyrtzidis | 64c438a | 2008-08-09 16:51:54 +0000 | [diff] [blame] | 777 | // signed/unsigned are only valid with int/char/wchar_t. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 778 | if (TypeSpecSign != TSS_unspecified) { | 
|  | 779 | if (TypeSpecType == TST_unspecified) | 
|  | 780 | TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. | 
| Argyrios Kyrtzidis | 64c438a | 2008-08-09 16:51:54 +0000 | [diff] [blame] | 781 | else if (TypeSpecType != TST_int  && | 
|  | 782 | TypeSpecType != TST_char && TypeSpecType != TST_wchar) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 783 | Diag(D, TSSLoc, diag::err_invalid_sign_spec) | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 784 | << getSpecifierName((TST)TypeSpecType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 785 | // signed double -> double. | 
|  | 786 | TypeSpecSign = TSS_unspecified; | 
|  | 787 | } | 
|  | 788 | } | 
|  | 789 |  | 
|  | 790 | // Validate the width of the type. | 
|  | 791 | switch (TypeSpecWidth) { | 
|  | 792 | case TSW_unspecified: break; | 
|  | 793 | case TSW_short:    // short int | 
|  | 794 | case TSW_longlong: // long long int | 
|  | 795 | if (TypeSpecType == TST_unspecified) | 
|  | 796 | TypeSpecType = TST_int; // short -> short int, long long -> long long int. | 
|  | 797 | else if (TypeSpecType != TST_int) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 798 | Diag(D, TSWLoc, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 799 | TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 800 | : diag::err_invalid_longlong_spec) | 
|  | 801 | <<  getSpecifierName((TST)TypeSpecType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 802 | TypeSpecType = TST_int; | 
| John McCall | 9e46b8c | 2010-08-26 17:22:34 +0000 | [diff] [blame] | 803 | TypeSpecOwned = false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 804 | } | 
|  | 805 | break; | 
|  | 806 | case TSW_long:  // long double, long int | 
|  | 807 | if (TypeSpecType == TST_unspecified) | 
|  | 808 | TypeSpecType = TST_int;  // long -> long int. | 
|  | 809 | else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 810 | Diag(D, TSWLoc, diag::err_invalid_long_spec) | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 811 | << getSpecifierName((TST)TypeSpecType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 812 | TypeSpecType = TST_int; | 
| John McCall | 9e46b8c | 2010-08-26 17:22:34 +0000 | [diff] [blame] | 813 | TypeSpecOwned = false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 814 | } | 
|  | 815 | break; | 
|  | 816 | } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 817 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 818 | // TODO: if the implementation does not implement _Complex or _Imaginary, | 
|  | 819 | // disallow their use.  Need information about the backend. | 
|  | 820 | if (TypeSpecComplex != TSC_unspecified) { | 
|  | 821 | if (TypeSpecType == TST_unspecified) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 822 | Diag(D, TSCLoc, diag::ext_plain_complex) | 
| Douglas Gregor | 849b243 | 2010-03-31 17:46:05 +0000 | [diff] [blame] | 823 | << FixItHint::CreateInsertion( | 
| Douglas Gregor | 9b3064b | 2009-04-01 22:41:11 +0000 | [diff] [blame] | 824 | PP.getLocForEndOfToken(getTypeSpecComplexLoc()), | 
|  | 825 | " double"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 826 | TypeSpecType = TST_double;   // _Complex -> _Complex double. | 
|  | 827 | } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) { | 
|  | 828 | // Note that this intentionally doesn't include _Complex _Bool. | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 829 | Diag(D, TSTLoc, diag::ext_integer_complex); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 830 | } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) { | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 831 | Diag(D, TSCLoc, diag::err_invalid_complex_spec) | 
| Chris Lattner | 254be6a | 2008-11-22 08:32:36 +0000 | [diff] [blame] | 832 | << getSpecifierName((TST)TypeSpecType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 833 | TypeSpecComplex = TSC_unspecified; | 
|  | 834 | } | 
|  | 835 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 836 |  | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 837 | // C++ [class.friend]p6: | 
|  | 838 | //   No storage-class-specifier shall appear in the decl-specifier-seq | 
|  | 839 | //   of a friend declaration. | 
|  | 840 | if (isFriendSpecified() && getStorageClassSpec()) { | 
|  | 841 | DeclSpec::SCS SC = getStorageClassSpec(); | 
|  | 842 | const char *SpecName = getSpecifierName(SC); | 
|  | 843 |  | 
|  | 844 | SourceLocation SCLoc = getStorageClassSpecLoc(); | 
|  | 845 | SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName)); | 
|  | 846 |  | 
| Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 847 | Diag(D, SCLoc, diag::err_friend_storage_spec) | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 848 | << SpecName | 
| Douglas Gregor | 849b243 | 2010-03-31 17:46:05 +0000 | [diff] [blame] | 849 | << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc)); | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 850 |  | 
|  | 851 | ClearStorageClassSpecs(); | 
|  | 852 | } | 
|  | 853 |  | 
| John McCall | 9e46b8c | 2010-08-26 17:22:34 +0000 | [diff] [blame] | 854 | assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType)); | 
|  | 855 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 856 | // Okay, now we can infer the real type. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 857 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 858 | // TODO: return "auto function" and other bad things based on the real type. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 859 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 860 | // 'data definition has no type or storage class'? | 
|  | 861 | } | 
| Daniel Dunbar | e4858a6 | 2008-08-11 03:45:03 +0000 | [diff] [blame] | 862 |  | 
| Sebastian Redl | a4ed0d8 | 2008-12-28 15:28:59 +0000 | [diff] [blame] | 863 | bool DeclSpec::isMissingDeclaratorOk() { | 
|  | 864 | TST tst = getTypeSpecType(); | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 865 | return isDeclRep(tst) && getRepAsDecl() != 0 && | 
|  | 866 | StorageClassSpec != DeclSpec::SCS_typedef; | 
| Sebastian Redl | a4ed0d8 | 2008-12-28 15:28:59 +0000 | [diff] [blame] | 867 | } | 
| Douglas Gregor | 3f9a056 | 2009-11-03 01:35:08 +0000 | [diff] [blame] | 868 |  | 
|  | 869 | void UnqualifiedId::clear() { | 
| Douglas Gregor | 3f9a056 | 2009-11-03 01:35:08 +0000 | [diff] [blame] | 870 | Kind = IK_Identifier; | 
|  | 871 | Identifier = 0; | 
|  | 872 | StartLocation = SourceLocation(); | 
|  | 873 | EndLocation = SourceLocation(); | 
|  | 874 | } | 
|  | 875 |  | 
|  | 876 | void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, | 
|  | 877 | OverloadedOperatorKind Op, | 
|  | 878 | SourceLocation SymbolLocations[3]) { | 
|  | 879 | Kind = IK_OperatorFunctionId; | 
|  | 880 | StartLocation = OperatorLoc; | 
|  | 881 | EndLocation = OperatorLoc; | 
|  | 882 | OperatorFunctionId.Operator = Op; | 
|  | 883 | for (unsigned I = 0; I != 3; ++I) { | 
|  | 884 | OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); | 
|  | 885 |  | 
|  | 886 | if (SymbolLocations[I].isValid()) | 
|  | 887 | EndLocation = SymbolLocations[I]; | 
|  | 888 | } | 
|  | 889 | } | 
| Anders Carlsson | b971dbd | 2011-01-17 03:05:47 +0000 | [diff] [blame] | 890 |  | 
| Anders Carlsson | cc54d59 | 2011-01-22 16:56:46 +0000 | [diff] [blame] | 891 | bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, | 
| Anders Carlsson | 46127a9 | 2011-01-22 15:58:16 +0000 | [diff] [blame] | 892 | const char *&PrevSpec) { | 
| Douglas Gregor | f525160 | 2011-03-08 17:10:18 +0000 | [diff] [blame] | 893 | LastLocation = Loc; | 
|  | 894 |  | 
| Anders Carlsson | b971dbd | 2011-01-17 03:05:47 +0000 | [diff] [blame] | 895 | if (Specifiers & VS) { | 
|  | 896 | PrevSpec = getSpecifierName(VS); | 
|  | 897 | return true; | 
|  | 898 | } | 
|  | 899 |  | 
|  | 900 | Specifiers |= VS; | 
|  | 901 |  | 
|  | 902 | switch (VS) { | 
|  | 903 | default: assert(0 && "Unknown specifier!"); | 
|  | 904 | case VS_Override: VS_overrideLoc = Loc; break; | 
|  | 905 | case VS_Final:    VS_finalLoc = Loc; break; | 
| Anders Carlsson | b971dbd | 2011-01-17 03:05:47 +0000 | [diff] [blame] | 906 | } | 
| Anders Carlsson | 46127a9 | 2011-01-22 15:58:16 +0000 | [diff] [blame] | 907 |  | 
| Anders Carlsson | b971dbd | 2011-01-17 03:05:47 +0000 | [diff] [blame] | 908 | return false; | 
|  | 909 | } | 
|  | 910 |  | 
| Anders Carlsson | cc54d59 | 2011-01-22 16:56:46 +0000 | [diff] [blame] | 911 | const char *VirtSpecifiers::getSpecifierName(Specifier VS) { | 
| Anders Carlsson | c46bb7d | 2011-01-22 15:11:37 +0000 | [diff] [blame] | 912 | switch (VS) { | 
|  | 913 | default: assert(0 && "Unknown specifier"); | 
|  | 914 | case VS_Override: return "override"; | 
|  | 915 | case VS_Final: return "final"; | 
| Anders Carlsson | c46bb7d | 2011-01-22 15:11:37 +0000 | [diff] [blame] | 916 | } | 
|  | 917 | } |