source: src/Validate/HandleAttributes.cc@ fd2debf

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum stuck-waitfor-destruct
Last change on this file since fd2debf was fd2debf, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Add checks for constructor/destructor attribute arguments

  • Property mode set to 100644
File size: 5.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// HandleAttributes.cc --
8//
9// Author : Rob Schluntz
10// Created On : Fri Jul 27 10:15:06 2018
11// Last Modified By : Rob Schluntz
12// Last Modified On : Fri Jul 27 10:16:43 2018
13// Update Count : 2
14//
15
16#include "HandleAttributes.h"
17
18#include <utility> // for pair
19
20#include "CompilationState.h"
21#include "Common/PassVisitor.h"
22#include "Common/SemanticError.h"
23#include "InitTweak/InitTweak.h"
24#include "ResolvExpr/Resolver.h"
25#include "SynTree/Attribute.h"
26#include "SynTree/Declaration.h"
27#include "SynTree/Type.h"
28
29namespace Validate {
30 namespace {
31 std::pair<long long int, bool> eval(Expression * expr);
32
33 struct Eval : public WithShortCircuiting {
34 long long int value = 0;
35 bool valid = true;
36
37 void previsit( BaseSyntaxNode * ) { visit_children = false; }
38 void postvisit( BaseSyntaxNode * ) { valid = false; }
39
40 void postvisit( ConstantExpr * expr ) {
41 value = expr->intValue();
42 }
43
44 void postvisit( CastExpr * expr ) {
45 auto arg = eval(expr->arg);
46 valid = arg.second;
47 value = arg.first;
48 // TODO: perform type conversion on value if valid
49 }
50
51 void postvisit( VariableExpr * expr ) {
52 if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
53 if ( EnumDecl * decl = inst->baseEnum ) {
54 if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
55 return;
56 }
57 }
58 }
59 valid = false;
60 }
61
62 void postvisit( ApplicationExpr * expr ) {
63 DeclarationWithType * function = InitTweak::getFunction(expr);
64 if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
65 const std::string & fname = function->name;
66 assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
67 std::pair<long long int, bool> arg1, arg2;
68 arg1 = eval(expr->args.front());
69 valid = valid && arg1.second;
70 if ( ! valid ) return;
71 if ( expr->args.size() == 2 ) {
72 arg2 = eval(expr->args.back());
73 valid = valid && arg2.second;
74 if ( ! valid ) return;
75 }
76 if (fname == "?+?") {
77 value = arg1.first + arg2.first;
78 } else if (fname == "?-?") {
79 value = arg1.first - arg2.first;
80 } else if (fname == "?*?") {
81 value = arg1.first * arg2.first;
82 } else if (fname == "?/?") {
83 value = arg1.first / arg2.first;
84 } else if (fname == "?%?") {
85 value = arg1.first % arg2.first;
86 } else {
87 valid = false;
88 }
89 // TODO: implement other intrinsic functions
90 }
91 };
92
93 std::pair<long long int, bool> eval(Expression * expr) {
94 PassVisitor<Eval> ev;
95 if (expr) {
96 expr->accept(ev);
97 return std::make_pair(ev.pass.value, ev.pass.valid);
98 } else {
99 return std::make_pair(0, false);
100 }
101 }
102
103 struct HandleAttributes : public WithIndexer {
104 void previsit( ObjectDecl * decl );
105 void previsit( FunctionDecl * decl );
106 };
107 } // namespace
108
109 void handleAttributes( std::list< Declaration * > &translationUnit ) {
110 PassVisitor<HandleAttributes> handler;
111 acceptAll( translationUnit, handler );
112 }
113
114 namespace {
115 void HandleAttributes::previsit( ObjectDecl * decl ) {
116 for ( Attribute * attr : decl->attributes ) {
117 std::string name = attr->normalizedName();
118 if (name == "init_priority") {
119
120 }
121 }
122 }
123
124 void HandleAttributes::previsit( FunctionDecl * decl ) {
125 for ( Attribute * attr : decl->attributes ) {
126 std::string name = attr->normalizedName();
127 if (name == "constructor" || name == "destructor") {
128 if (attr->parameters.size() == 1) {
129 Expression *& arg = attr->parameters.front();
130 ResolvExpr::findSingleExpression( arg, new BasicType( Type::Qualifiers(), BasicType::LongLongSignedInt ), indexer );
131 auto result = eval(arg);
132 if (! result.second) {
133 SemanticWarning(attr->location, Warning::GccAttributes,
134 toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
135 return;
136 }
137 auto priority = result.first;
138 if (priority < 101) {
139 SemanticWarning(attr->location, Warning::GccAttributes,
140 toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
141 } else if (priority < 201) {
142 SemanticWarning(attr->location, Warning::GccAttributes,
143 toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
144 }
145 } else if (attr->parameters.size() > 1) {
146 SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
147 } else {
148 SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
149 }
150 }
151 }
152 }
153 } // namespace
154} // namespace Validate
155
156// Local Variables: //
157// tab-width: 4 //
158// mode: c++ //
159// compile-command: "make install" //
160// End: //
Note: See TracBrowser for help on using the repository browser.