aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-03-06 20:05:56 +0000
committerTed Kremenek <kremenek@apple.com>2012-03-06 20:05:56 +0000
commitebcb57a8d298862c65043e88b2429591ab3c58d3 (patch)
treeadbe4e0a60340ec2858e4b8d74d7bb0f23887d67
parent9f86af897458b3b44e26b9e06a857f626f71a692 (diff)
Add clang support for new Objective-C literal syntax for NSDictionary, NSArray,
NSNumber, and boolean literals. This includes both Sema and Codegen support. Included is also support for new Objective-C container subscripting. My apologies for the large patch. It was very difficult to break apart. The patch introduces changes to the driver as well to cause clang to link in additional runtime support when needed to support the new language features. Docs are forthcoming to document the implementation and behavior of these features. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152137 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h1
-rw-r--r--include/clang/AST/ExprObjC.h358
-rw-r--r--include/clang/AST/NSAPI.h151
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h7
-rw-r--r--include/clang/AST/Stmt.h2
-rw-r--r--include/clang/Basic/DiagnosticGroups.td10
-rw-r--r--include/clang/Basic/DiagnosticIDs.h2
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td66
-rw-r--r--include/clang/Basic/LangOptions.def1
-rw-r--r--include/clang/Basic/Specifiers.h7
-rw-r--r--include/clang/Basic/StmtNodes.td5
-rw-r--r--include/clang/Basic/TokenKinds.def3
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/Driver/ObjCRuntime.h5
-rw-r--r--include/clang/Driver/Options.td1
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h1
-rw-r--r--include/clang/Parse/Parser.h9
-rw-r--r--include/clang/Sema/Sema.h59
-rw-r--r--include/clang/Serialization/ASTBitCodes.h10
-rw-r--r--lib/AST/ASTContext.cpp5
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Expr.cpp121
-rw-r--r--lib/AST/ExprClassification.cpp5
-rw-r--r--lib/AST/ExprConstant.cpp11
-rw-r--r--lib/AST/ItaniumMangle.cpp11
-rw-r--r--lib/AST/NSAPI.cpp311
-rw-r--r--lib/AST/StmtDumper.cpp29
-rw-r--r--lib/AST/StmtPrinter.cpp47
-rw-r--r--lib/AST/StmtProfile.cpp23
-rw-r--r--lib/CodeGen/CGExprScalar.cpp12
-rw-r--r--lib/CodeGen/CGObjC.cpp216
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp7
-rw-r--r--lib/CodeGen/CGObjCMac.cpp53
-rw-r--r--lib/CodeGen/CGObjCRuntime.h6
-rw-r--r--lib/CodeGen/CodeGenFunction.h5
-rw-r--r--lib/Driver/ToolChains.cpp5
-rw-r--r--lib/Driver/ToolChains.h7
-rw-r--r--lib/Driver/Tools.cpp35
-rw-r--r--lib/Lex/PPMacroExpansion.cpp4
-rw-r--r--lib/Parse/ParseExpr.cpp13
-rw-r--r--lib/Parse/ParseObjc.cpp181
-rw-r--r--lib/Sema/Sema.cpp9
-rw-r--r--lib/Sema/SemaCast.cpp2
-rw-r--r--lib/Sema/SemaCodeComplete.cpp20
-rw-r--r--lib/Sema/SemaExpr.cpp25
-rw-r--r--lib/Sema/SemaExprCXX.cpp27
-rw-r--r--lib/Sema/SemaExprObjC.cpp674
-rw-r--r--lib/Sema/SemaPseudoObject.cpp505
-rw-r--r--lib/Sema/SemaStmt.cpp8
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp16
-rw-r--r--lib/Sema/TreeTransform.h208
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp72
-rw-r--r--lib/Serialization/ASTWriter.cpp4
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp60
-rw-r--r--test/CodeGenObjC/Inputs/literal-support.h35
-rw-r--r--test/CodeGenObjC/arc-literals.m121
-rw-r--r--test/CodeGenObjC/objc-arc-container-subscripting.m21
-rw-r--r--test/CodeGenObjC/objc-container-subscripting-1.m56
-rw-r--r--test/CodeGenObjC/objc-container-subscripting.m45
-rw-r--r--test/CodeGenObjC/objc-dictionary-literal.m25
-rw-r--r--test/CodeGenObjC/objc-literal-debugger-test.m16
-rw-r--r--test/CodeGenObjC/objc-literal-tests.m95
-rw-r--r--test/CodeGenObjC/optimized-setter.m33
-rw-r--r--test/CodeGenObjCXX/Inputs/literal-support.h35
-rw-r--r--test/CodeGenObjCXX/literals.mm111
-rw-r--r--test/CodeGenObjCXX/objc-container-subscripting-1.mm50
-rw-r--r--test/CodeGenObjCXX/objc-container-subscripting.mm57
-rw-r--r--test/Driver/arclite-link.c8
-rw-r--r--test/Driver/darwin-ld.c4
-rw-r--r--test/Driver/rewrite-objc.m2
-rw-r--r--test/PCH/objc_container.h26
-rw-r--r--test/PCH/objc_container.m20
-rw-r--r--test/PCH/objc_literals.m66
-rw-r--r--test/PCH/objc_literals.mm65
-rw-r--r--test/PCH/subscripting-literals.m47
-rw-r--r--test/SemaObjC/cocoa-api-usage.m88
-rw-r--r--test/SemaObjC/cocoa-api-usage.m.fixed88
-rw-r--r--test/SemaObjC/invalid-code.m3
-rw-r--r--test/SemaObjC/objc-array-literal.m41
-rw-r--r--test/SemaObjC/objc-container-subscripting-1.m23
-rw-r--r--test/SemaObjC/objc-container-subscripting-2.m30
-rw-r--r--test/SemaObjC/objc-container-subscripting-3.m25
-rw-r--r--test/SemaObjC/objc-container-subscripting.m42
-rw-r--r--test/SemaObjC/objc-literal-nsnumber.m78
-rw-r--r--test/SemaObjC/objc-literal-sig.m40
-rw-r--r--test/SemaObjC/sizeof-interface.m6
-rw-r--r--test/SemaObjCXX/literals.mm178
-rw-r--r--test/SemaObjCXX/objc-container-subscripting.mm138
89 files changed, 5092 insertions, 68 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 695db67f24..67876170e4 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -564,6 +564,7 @@ public:
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
+ CanQualType ObjCBuiltinBoolTy;
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 6e8c60adcf..c3a6880a26 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Sema/Ownership.h"
namespace clang {
class IdentifierInfo;
@@ -56,6 +57,281 @@ public:
child_range children() { return child_range(&String, &String+1); }
};
+/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
+///
+class ObjCBoolLiteralExpr : public Expr {
+ bool Value;
+ SourceLocation Loc;
+public:
+ ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
+ Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false, false), Value(val), Loc(l) {}
+
+ explicit ObjCBoolLiteralExpr(EmptyShell Empty)
+ : Expr(ObjCBoolLiteralExprClass, Empty) { }
+
+ bool getValue() const { return Value; }
+ void setValue(bool V) { Value = V; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBoolLiteralExprClass;
+ }
+ static bool classof(const ObjCBoolLiteralExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ObjCNumericLiteral - used for objective-c numeric literals;
+/// as in: @42 or @true (c++/objc++) or @__yes (c/objc)
+class ObjCNumericLiteral : public Expr {
+ /// Number - expression AST node for the numeric literal
+ Stmt *Number;
+ ObjCMethodDecl *ObjCNumericLiteralMethod;
+ SourceLocation AtLoc;
+public:
+ ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method,
+ SourceLocation L)
+ : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary,
+ false, false, false, false), Number(NL),
+ ObjCNumericLiteralMethod(method), AtLoc(L) {}
+ explicit ObjCNumericLiteral(EmptyShell Empty)
+ : Expr(ObjCNumericLiteralClass, Empty) {}
+
+ Expr *getNumber() { return cast<Expr>(Number); }
+ const Expr *getNumber() const { return cast<Expr>(Number); }
+
+ ObjCMethodDecl *getObjCNumericLiteralMethod() const {
+ return ObjCNumericLiteralMethod;
+ }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, Number->getSourceRange().getEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCNumericLiteralClass;
+ }
+ static bool classof(const ObjCNumericLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Number, &Number+1); }
+
+ friend class ASTStmtReader;
+};
+
+/// ObjCArrayLiteral - used for objective-c array containers; as in:
+/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
+class ObjCArrayLiteral : public Expr {
+ unsigned NumElements;
+ SourceRange Range;
+ ObjCMethodDecl *ArrayWithObjectsMethod;
+
+ ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl * Method,
+ SourceRange SR);
+
+ explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
+ : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
+
+public:
+ static ObjCArrayLiteral *Create(ASTContext &C,
+ llvm::ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl * Method,
+ SourceRange SR);
+
+ static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements);
+
+ SourceRange getSourceRange() const { return Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCArrayLiteralClass;
+ }
+ static bool classof(const ObjCArrayLiteral *) { return true; }
+
+ /// \brief Retrieve elements of array of literals.
+ Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); }
+
+ /// \brief Retrieve elements of array of literals.
+ const Expr * const *getElements() const {
+ return reinterpret_cast<const Expr * const*>(this + 1);
+ }
+
+ /// getNumElements - Return number of elements of objective-c array literal.
+ unsigned getNumElements() const { return NumElements; }
+
+ /// getExpr - Return the Expr at the specified index.
+ Expr *getElement(unsigned Index) {
+ assert((Index < NumElements) && "Arg access out of range!");
+ return cast<Expr>(getElements()[Index]);
+ }
+ const Expr *getElement(unsigned Index) const {
+ assert((Index < NumElements) && "Arg access out of range!");
+ return cast<Expr>(getElements()[Index]);
+ }
+
+ ObjCMethodDecl *getArrayWithObjectsMethod() const {
+ return ArrayWithObjectsMethod;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range((Stmt **)getElements(),
+ (Stmt **)getElements() + NumElements);
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief An element in an Objective-C dictionary literal.
+///
+struct ObjCDictionaryElement {
+ /// \brief The key for the dictionary element.
+ Expr *Key;
+
+ /// \brief The value of the dictionary element.
+ Expr *Value;
+
+ /// \brief The location of the ellipsis, if this is a pack expansion.
+ SourceLocation EllipsisLoc;
+
+ /// \brief The number of elements this pack expansion will expand to, if
+ /// this is a pack expansion and is known.
+ llvm::Optional<unsigned> NumExpansions;
+
+ /// \brief Determines whether this dictionary element is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+};
+
+/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
+/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
+class ObjCDictionaryLiteral : public Expr {
+ /// \brief Key/value pair used to store the key and value of a given element.
+ ///
+ /// Objects of this type are stored directly after the expression.
+ struct KeyValuePair {
+ Expr *Key;
+ Expr *Value;
+ };
+
+ /// \brief Data that describes an element that is a pack expansion, used if any
+ /// of the elements in the dictionary literal are pack expansions.
+ struct ExpansionData {
+ /// \brief The location of the ellipsis, if this element is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
+ /// \brief If non-zero, the number of elements that this pack
+ /// expansion will expand to (+1).
+ unsigned NumExpansionsPlusOne;
+ };
+
+ /// \brief The number of elements in this dictionary literal.
+ unsigned NumElements : 31;
+
+ /// \brief Determine whether this dictionary literal has any pack expansions.
+ ///
+ /// If the dictionary literal has pack expansions, then there will
+ /// be an array of pack expansion data following the array of
+ /// key/value pairs, which provide the locations of the ellipses (if
+ /// any) and number of elements in the expansion (if known). If
+ /// there are no pack expansions, we optimize away this storage.
+ unsigned HasPackExpansions : 1;
+
+ SourceRange Range;
+ ObjCMethodDecl *DictWithObjectsMethod;
+
+ ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR);
+
+ explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
+ bool HasPackExpansions)
+ : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
+ HasPackExpansions(HasPackExpansions) {}
+
+ KeyValuePair *getKeyValues() {
+ return reinterpret_cast<KeyValuePair *>(this + 1);
+ }
+
+ const KeyValuePair *getKeyValues() const {
+ return reinterpret_cast<const KeyValuePair *>(this + 1);
+ }
+
+ ExpansionData *getExpansionData() {
+ if (!HasPackExpansions)
+ return 0;
+
+ return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
+ }
+
+ const ExpansionData *getExpansionData() const {
+ if (!HasPackExpansions)
+ return 0;
+
+ return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
+ }
+
+public:
+ static ObjCDictionaryLiteral *Create(ASTContext &C,
+ ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR);
+
+ static ObjCDictionaryLiteral *CreateEmpty(ASTContext &C,
+ unsigned NumElements,
+ bool HasPackExpansions);
+
+ /// getNumElements - Return number of elements of objective-c dictionary
+ /// literal.
+ unsigned getNumElements() const { return NumElements; }
+
+ ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
+ assert((Index < NumElements) && "Arg access out of range!");
+ const KeyValuePair &KV = getKeyValues()[Index];
+ ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(),
+ llvm::Optional<unsigned>() };
+ if (HasPackExpansions) {
+ const ExpansionData &Expansion = getExpansionData()[Index];
+ Result.EllipsisLoc = Expansion.EllipsisLoc;
+ if (Expansion.NumExpansionsPlusOne > 0)
+ Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
+ }
+ return Result;
+ }
+
+ ObjCMethodDecl *getDictWithObjectsMethod() const
+ { return DictWithObjectsMethod; }
+
+ SourceRange getSourceRange() const { return Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCDictionaryLiteralClass;
+ }
+ static bool classof(const ObjCDictionaryLiteral *) { return true; }
+
+ // Iterators
+ child_range children() {
+ // Note: we're taking advantage of the layout of the KeyValuePair struct
+ // here. If that struct changes, this code will need to change as well.
+ return child_range(reinterpret_cast<Stmt **>(this + 1),
+ reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+
/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
/// and behavior as StringLiteral except that the string initializer is obtained
/// from ASTContext with the encoding type as an argument.
@@ -430,6 +706,88 @@ private:
void setLocation(SourceLocation L) { IdLoc = L; }
void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
};
+
+/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
+/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
+///
+class ObjCSubscriptRefExpr : public Expr {
+ // Location of ']' in an indexing expression.
+ SourceLocation RBracket;
+ // array/dictionary base expression.
+ // for arrays, this is a numeric expression. For dictionaries, this is
+ // an objective-c object pointer expression.
+ enum { BASE, KEY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+
+ ObjCMethodDecl *GetAtIndexMethodDecl;
+
+ // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
+ // an indexed object this is null too.
+ ObjCMethodDecl *SetAtIndexMethodDecl;
+
+public:
+
+ ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
+ ExprValueKind VK, ExprObjectKind OK,
+ ObjCMethodDecl *getMethod,
+ ObjCMethodDecl *setMethod, SourceLocation RB)
+