blob: 9bb191d52bbf4af6156d8d0264f36598ca2bcaa0 [file] [log] [blame]
Richard Smithc202b282012-04-14 00:33:13 +00001//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements stmt-related attribute processing.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/SemaInternal.h"
Richard Smithc202b282012-04-14 00:33:13 +000015#include "clang/AST/ASTContext.h"
16#include "clang/Basic/SourceManager.h"
Richard Smith84837d52012-05-03 18:27:39 +000017#include "clang/Lex/Lexer.h"
Richard Smithc202b282012-04-14 00:33:13 +000018#include "clang/Sema/DelayedDiagnostic.h"
19#include "clang/Sema/Lookup.h"
Richard Smith84837d52012-05-03 18:27:39 +000020#include "clang/Sema/ScopeInfo.h"
Richard Smithc202b282012-04-14 00:33:13 +000021#include "llvm/ADT/StringExtras.h"
Richard Smith84837d52012-05-03 18:27:39 +000022
Richard Smithc202b282012-04-14 00:33:13 +000023using namespace clang;
24using namespace sema;
25
Richard Smith84837d52012-05-03 18:27:39 +000026static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
27 SourceRange Range) {
28 if (!isa<NullStmt>(St)) {
29 S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
30 << St->getLocStart();
31 if (isa<SwitchCase>(St)) {
32 SourceLocation L = Lexer::getLocForEndOfToken(Range.getEnd(), 0,
33 S.getSourceManager(), S.getLangOpts());
34 S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
35 << FixItHint::CreateInsertion(L, ";");
36 }
37 return 0;
38 }
39 if (S.getCurFunction()->SwitchStack.empty()) {
40 S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
41 return 0;
42 }
Aaron Ballman36a53502014-01-16 13:03:14 +000043 return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
44 A.getAttributeSpellingListIndex());
Richard Smith84837d52012-05-03 18:27:39 +000045}
Richard Smithc202b282012-04-14 00:33:13 +000046
Richard Smith84837d52012-05-03 18:27:39 +000047
48static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
49 SourceRange Range) {
Richard Smithc202b282012-04-14 00:33:13 +000050 switch (A.getKind()) {
Michael Han23214e52012-10-03 01:56:22 +000051 case AttributeList::UnknownAttribute:
52 S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
53 diag::warn_unhandled_ms_attribute_ignored :
54 diag::warn_unknown_attribute_ignored) << A.getName();
55 return 0;
Alexis Hunt3bc72c12012-06-19 23:57:03 +000056 case AttributeList::AT_FallThrough:
Richard Smith84837d52012-05-03 18:27:39 +000057 return handleFallThroughAttr(S, St, A, Range);
Richard Smithc202b282012-04-14 00:33:13 +000058 default:
Michael Han23214e52012-10-03 01:56:22 +000059 // if we're here, then we parsed a known attribute, but didn't recognize
60 // it as a statement attribute => it is declaration attribute
Richard Smith4c96e992013-02-19 23:47:15 +000061 S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
62 << A.getName() << St->getLocStart();
Richard Smithc202b282012-04-14 00:33:13 +000063 return 0;
64 }
65}
66
67StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
68 SourceRange Range) {
Alexander Kornienko20f6fc62012-07-09 10:04:07 +000069 SmallVector<const Attr*, 8> Attrs;
Richard Smithc202b282012-04-14 00:33:13 +000070 for (const AttributeList* l = AttrList; l; l = l->getNext()) {
Richard Smith84837d52012-05-03 18:27:39 +000071 if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
Richard Smithc202b282012-04-14 00:33:13 +000072 Attrs.push_back(a);
73 }
74
75 if (Attrs.empty())
76 return S;
77
78 return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
79}