Merge remote-tracking branch 'origin/swift-3.0-branch' into stable
* origin/swift-3.0-branch:
[test/objcmt] Add a follow-up test case for r275600.
[objcmt] Fix a buffer overflow crash than can occur while modernizing enums.
[AST] Keep track of the left brace source location of a tag decl.
[objcmt] Don't add an #import of Foundation unnecessarily, if the NS_ENUM macro is already defined.
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 29b19f2..73e004b 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -2700,7 +2700,7 @@
/// the TU.
bool IsCompleteDefinitionRequired : 1;
private:
- SourceLocation RBraceLoc;
+ SourceRange BraceRange;
// A struct representing syntactic qualifier info,
// to be used for the (uncommon) case of out-of-line declarations.
@@ -2762,8 +2762,8 @@
using redeclarable_base::getMostRecentDecl;
using redeclarable_base::isFirstDecl;
- SourceLocation getRBraceLoc() const { return RBraceLoc; }
- void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+ SourceRange getBraceRange() const { return BraceRange; }
+ void setBraceRange(SourceRange R) { BraceRange = R; }
/// getInnerLocStart - Return SourceLocation representing start of source
/// range ignoring outer template declarations.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 32f249e..ecbc305 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2001,7 +2001,7 @@
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
/// the definition of a tag (enumeration, class, struct, or union).
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
- SourceLocation RBraceLoc);
+ SourceRange BraceRange);
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
@@ -2038,8 +2038,8 @@
SourceLocation IdLoc, IdentifierInfo *Id,
AttributeList *Attrs,
SourceLocation EqualLoc, Expr *Val);
- void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, Decl *EnumDecl,
+ void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
+ Decl *EnumDecl,
ArrayRef<Decl *> Elements,
Scope *S, AttributeList *Attr);
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 3737914..a233a4c 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -772,23 +772,11 @@
ClassString += ", ";
ClassString += TypedefDcl->getIdentifier()->getName();
- ClassString += ')';
- SourceLocation EndLoc;
- if (EnumDcl->getIntegerTypeSourceInfo()) {
- TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo();
- TypeLoc TLoc = TSourceInfo->getTypeLoc();
- EndLoc = TLoc.getLocEnd();
- const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc);
- unsigned count = 0;
- if (lbrace)
- while (lbrace[count] != '{')
- ++count;
- if (count > 0)
- EndLoc = EndLoc.getLocWithOffset(count-1);
- }
- else
- EndLoc = EnumDcl->getLocStart();
- SourceRange R(EnumDcl->getLocStart(), EndLoc);
+ ClassString += ") ";
+ SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
+ if (EndLoc.isInvalid())
+ return;
+ CharSourceRange R = CharSourceRange::getCharRange(EnumDcl->getLocStart(), EndLoc);
commit.replace(R, ClassString);
// This is to remove spaces between '}' and typedef name.
SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
@@ -1741,6 +1729,11 @@
return true;
if (Loc.isInvalid())
return false;
+ auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");
+ if (PP.getMacroDefinitionAtLoc(nsEnumId, Loc)) {
+ FoundationIncluded = true;
+ return true;
+ }
edit::Commit commit(*Editor);
if (Ctx.getLangOpts().Modules)
commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
@@ -1899,18 +1892,20 @@
if (++N == DEnd)
continue;
if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
- if (++N != DEnd)
- if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
- // prefer typedef-follows-enum to enum-follows-typedef pattern.
- if (migrateNSEnumDecl(Ctx, ED, TDF)) {
- ++D; ++D;
- CacheObjCNSIntegerTypedefed(TD);
- continue;
+ if (canModify(ED)) {
+ if (++N != DEnd)
+ if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
+ // prefer typedef-follows-enum to enum-follows-typedef pattern.
+ if (migrateNSEnumDecl(Ctx, ED, TDF)) {
+ ++D; ++D;
+ CacheObjCNSIntegerTypedefed(TD);
+ continue;
+ }
}
+ if (migrateNSEnumDecl(Ctx, ED, TD)) {
+ ++D;
+ continue;
}
- if (migrateNSEnumDecl(Ctx, ED, TD)) {
- ++D;
- continue;
}
}
CacheObjCNSIntegerTypedefed(TD);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index eb1a10e..3a513e5 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3520,6 +3520,7 @@
}
SourceRange TagDecl::getSourceRange() const {
+ SourceLocation RBraceLoc = BraceRange.getEnd();
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
return SourceRange(getOuterLocStart(), E);
}
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index de3ebd2..f68bf4b 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -806,7 +806,7 @@
getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
if (getExternLoc().isValid())
Begin = getExternLoc();
- SourceLocation End = getRBraceLoc();
+ SourceLocation End = getBraceRange().getEnd();
if (End.isInvalid())
End = getTypeAsWritten()->getTypeLoc().getEndLoc();
return SourceRange(Begin, End);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 38b3096..d41a1ac 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3759,8 +3759,7 @@
T.getOpenLocation(), T.getCloseLocation(),
attrs.getList());
StructScope.Exit();
- Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl,
- T.getCloseLocation());
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
}
/// ParseEnumSpecifier
@@ -4255,7 +4254,7 @@
ParsedAttributes attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
- Actions.ActOnEnumBody(StartLoc, T.getOpenLocation(), T.getCloseLocation(),
+ Actions.ActOnEnumBody(StartLoc, T.getRange(),
EnumDecl, EnumConstantDecls,
getCurScope(),
attrs.getList());
@@ -4269,8 +4268,7 @@
}
EnumScope.Exit();
- Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,
- T.getCloseLocation());
+ Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange());
// The next token must be valid after an enum definition. If not, a ';'
// was probably forgotten.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index b2337b2..5a90b6c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -3122,8 +3122,7 @@
}
if (TagDecl)
- Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl,
- T.getCloseLocation());
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
// Leave the class scope.
ParsingDef.Pop();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8edbddf..6158d33 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12751,10 +12751,10 @@
}
void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
- SourceLocation RBraceLoc) {
+ SourceRange BraceRange) {
AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD);
- Tag->setRBraceLoc(RBraceLoc);
+ Tag->setBraceRange(BraceRange);
// Make sure we "complete" the definition even it is invalid.
if (Tag->isBeingDefined()) {
@@ -14351,8 +14351,8 @@
return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
}
-void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, Decl *EnumDeclX,
+void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
+ Decl *EnumDeclX,
ArrayRef<Decl *> Elements,
Scope *S, AttributeList *Attr) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 8b7837b..0c18faf 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -7426,7 +7426,7 @@
// Set source locations for keywords.
Specialization->setExternLoc(ExternLoc);
Specialization->setTemplateKeywordLoc(TemplateLoc);
- Specialization->setRBraceLoc(SourceLocation());
+ Specialization->setBraceRange(SourceRange());
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index f81c96b..caf8693 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2082,7 +2082,7 @@
if (TSK == TSK_ImplicitInstantiation) {
Instantiation->setLocation(Pattern->getLocation());
Instantiation->setLocStart(Pattern->getInnerLocStart());
- Instantiation->setRBraceLoc(Pattern->getRBraceLoc());
+ Instantiation->setBraceRange(Pattern->getBraceRange());
}
if (!Instantiation->isInvalidDecl()) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4a274fd..8adc88f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -925,9 +925,7 @@
}
}
- // FIXME: Fixup LBraceLoc
- SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(),
- Enum->getRBraceLoc(), Enum,
+ SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum,
Enumerators,
nullptr, nullptr);
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 3f7f25d..6f60b63 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -591,7 +591,7 @@
TD->setEmbeddedInDeclarator(Record[Idx++]);
TD->setFreeStanding(Record[Idx++]);
TD->setCompleteDefinitionRequired(Record[Idx++]);
- TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
+ TD->setBraceRange(ReadSourceRange(Record, Idx));
switch (Record[Idx++]) {
case 0:
@@ -3719,7 +3719,7 @@
RD->setTagKind((TagTypeKind)Record[Idx++]);
RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
- RD->setRBraceLoc(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ RD->setBraceRange(Reader.ReadSourceRange(ModuleFile, Record, Idx));
if (Record[Idx++]) {
AttrVec Attrs;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 62c60a0..cd0d62f 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -4682,7 +4682,7 @@
Record.push_back(RD->getTagKind());
AddSourceLocation(RD->getLocation(), Record);
AddSourceLocation(RD->getLocStart(), Record);
- AddSourceLocation(RD->getRBraceLoc(), Record);
+ AddSourceRange(RD->getBraceRange(), Record);
// Instantiation may change attributes; write them all out afresh.
Record.push_back(D->hasAttrs());
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 64985a2..49893dc 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -373,7 +373,7 @@
Record.push_back(D->isEmbeddedInDeclarator());
Record.push_back(D->isFreeStanding());
Record.push_back(D->isCompleteDefinitionRequired());
- Writer.AddSourceLocation(D->getRBraceLoc(), Record);
+ Writer.AddSourceRange(D->getBraceRange(), Record);
if (D->hasExtInfo()) {
Record.push_back(1);
@@ -1738,6 +1738,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind
// EnumDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddTypeRef
@@ -1786,6 +1787,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind
// RecordDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember
diff --git a/test/ARCMT/objcmt-ns-enum-crash.m b/test/ARCMT/objcmt-ns-enum-crash.m
new file mode 100644
index 0000000..7c9c708
--- /dev/null
+++ b/test/ARCMT/objcmt-ns-enum-crash.m
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-ns-macros -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+
+#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
+#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
+typedef long NSInteger;
+
+typedef enum : NSInteger {five} ApplicableEnum;
+
+typedef unsigned long mytd;
+
+#define MY_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
+MY_ENUM(MyEnum, unsigned int, One);
diff --git a/test/ARCMT/objcmt-ns-enum-crash.m.result b/test/ARCMT/objcmt-ns-enum-crash.m.result
new file mode 100644
index 0000000..0a76e66
--- /dev/null
+++ b/test/ARCMT/objcmt-ns-enum-crash.m.result
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-ns-macros -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+
+#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
+#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
+typedef long NSInteger;
+
+typedef NS_ENUM(NSInteger, ApplicableEnum) {five};
+
+typedef unsigned long mytd;
+
+#define MY_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
+MY_ENUM(MyEnum, unsigned int, One);
diff --git a/test/ARCMT/objcmt-ns-macros.m.result b/test/ARCMT/objcmt-ns-macros.m.result
index bcc865c..0107827 100644
--- a/test/ARCMT/objcmt-ns-macros.m.result
+++ b/test/ARCMT/objcmt-ns-macros.m.result
@@ -19,9 +19,6 @@
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
#define DEPRECATED __attribute__((deprecated))
-#ifndef NS_ENUM
-#import <Foundation/Foundation.h>
-#endif
typedef NS_ENUM(NSInteger, wibble) {
blah,
blarg
@@ -80,7 +77,7 @@
UIKTwo = 2,
};
-typedef NS_ENUM(unsigned int, NSTickMarkPosition) {
+typedef NS_ENUM(unsigned int, NSTickMarkPosition) {
NSTickMarkBelow = 0,
NSTickMarkAbove = 1,
NSTickMarkLeft = NSTickMarkAbove,
diff --git a/test/ARCMT/whitelisted/header1.h b/test/ARCMT/whitelisted/header1.h
index d94b9f7..33f77aa 100644
--- a/test/ARCMT/whitelisted/header1.h
+++ b/test/ARCMT/whitelisted/header1.h
@@ -4,3 +4,5 @@
-(void)setProp:(int)p;
+(id)i1;
@end
+
+typedef long NSInteger;
diff --git a/test/ARCMT/whitelisted/header1.h.result b/test/ARCMT/whitelisted/header1.h.result
index 65cbd26..c7cf109 100644
--- a/test/ARCMT/whitelisted/header1.h.result
+++ b/test/ARCMT/whitelisted/header1.h.result
@@ -3,3 +3,5 @@
@property (nonatomic) int prop;
+(instancetype)i1;
@end
+
+typedef long NSInteger;
diff --git a/test/ARCMT/whitelisted/header2.h b/test/ARCMT/whitelisted/header2.h
index c7577ed..ac3888c 100644
--- a/test/ARCMT/whitelisted/header2.h
+++ b/test/ARCMT/whitelisted/header2.h
@@ -1,4 +1,7 @@
+#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
+typedef enum : NSInteger {five} ApplicableEnum;
+
@interface I2 : NSObject
-(int)prop;
-(void)setProp:(int)p;
diff --git a/test/ARCMT/whitelisted/header2.h.result b/test/ARCMT/whitelisted/header2.h.result
index b1b5270..3226e71 100644
--- a/test/ARCMT/whitelisted/header2.h.result
+++ b/test/ARCMT/whitelisted/header2.h.result
@@ -1,4 +1,7 @@
+#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
+typedef NS_ENUM(NSInteger, ApplicableEnum) {five};
+
@interface I2 : NSObject
@property (nonatomic) int prop;
@end
diff --git a/test/ARCMT/whitelisted/objcmt-with-whitelist.m b/test/ARCMT/whitelisted/objcmt-with-whitelist.m
index bef82c8..0ea714f 100644
--- a/test/ARCMT/whitelisted/objcmt-with-whitelist.m
+++ b/test/ARCMT/whitelisted/objcmt-with-whitelist.m
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-instancetype %s -triple x86_64-apple-darwin11 -migrate -o %t.remap
+// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-instancetype -objcmt-migrate-ns-macros %s -triple x86_64-apple-darwin11 -migrate -o %t.remap
// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %S/header1.h.result %S/header2.h.result
-// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-instancetype -objcmt-white-list-dir-path=%S/Inputs %s -triple x86_64-apple-darwin11 -migrate -o %t.remap
+// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-instancetype -objcmt-migrate-ns-macros -objcmt-white-list-dir-path=%S/Inputs %s -triple x86_64-apple-darwin11 -migrate -o %t.remap
// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %S/header1.h.result
@interface NSObject